question

giorgiotino avatar image
giorgiotino asked

Unhadled exception with HttpWebRequest

I had to switch to HttpWebRequest RequestType after figuring out that the Unity Web Request does not support timeouts.

The exception seems to happen whenever the app is killed or stopped by the Editor:


UnityException: FindObjectsOfType can only be called from the main thread.
Constructors and field initializers will be executed from the loading thread when loading a scene.
Don't use this function in the constructor or field initializers, instead move initialization code to the Awake or Start function.
UnityEngine.Object.FindObjectOfType (System.Type type) (at <a979f18d51af41179d12b797e8c5be14>:0)
UnityEngine.Object.FindObjectOfType[T] () (at <a979f18d51af41179d12b797e8c5be14>:0)
PlayFab.Internal.SingletonMonoBehaviour`1[T].CreateInstance () (at Assets/Externals/PlayFabSDK/Shared/Internal/SingletonMonoBehaviour.cs:24)
PlayFab.Internal.SingletonMonoBehaviour`1[T].get_instance () (at Assets/Externals/PlayFabSDK/Shared/Internal/SingletonMonoBehaviour.cs:14)
PlayFab.Internal.PlayFabWebRequest.ProcessJsonResponse (PlayFab.Internal.CallRequestContainer reqContainer) (at Assets/Externals/PlayFabSDK/Shared/Internal/PlayFabHttp/PlayFabWebRequest.cs:423)
Rethrow as Exception: Unhandled exception in ProcessJsonResponse : https://2746B.playfabapi.com/Event/WriteEvents?sdk=UnitySDK-2.89.200629
UnityEngine.Debug:LogException(Exception)
PlayFab.Internal.PlayFabWebRequest:ProcessJsonResponse(CallRequestContainer) (at Assets/Externals/PlayFabSDK/Shared/Internal/PlayFabHttp/PlayFabWebRequest.cs:458)
PlayFab.Internal.PlayFabWebRequest:WorkerThreadMainLoop() (at Assets/Externals/PlayFabSDK/Shared/Internal/PlayFabHttp/PlayFabWebRequest.cs:258)
System.Threading.ThreadHelper:ThreadStart()

Looks like the instance that is supposed to be there has already been destroyed somehow, so it's null and tries to recreate itself in the workerthread, or something like that.

This is what I think it is going on:

The mouse leaves the active Game tab
The lost focus event is enqueued and EventWrite is called
Clicking on the Editor Stop button kills the running app
Somehow the EventWrite returns, but the PlayFabHttp.instance is null and gets recreated on the fly
BOOM


I assume the problem is that stopping the app from the Editor could mess with the way EventWrite API gets triggered. It is my understanding (but correct me if I am wrong) that quitting the app/losing the focus triggers the WriteEvents API, BUT somehow in the case of quitting the app something has already been disposed when the handler is called when the response gets back. The instance is not there anymore (possibly due to the app being killed?), the singleton accessor tries to create a new one but we are in the worker thread and the exception is raised.

Now, this is scary as it seems to me that the app could crash every time it gets closed on the device, which is definitely not a good thing.

Am I missing something here? Is there a workaround or maybe a better way to handle this scenario?

apis
10 |1200

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

1 Answer

·
Sarah Zhang avatar image
Sarah Zhang answered

You should be right. Temporarily, you can modify the SDK manually to prevent the thread calls the FindObjectsOfType after the application has quit.

Please find this script – PlayFabWebRequest.cs in your Unity project. This script has already defined a flag _isApplicationPlaying to mark whether the script is destroyed. You can use it to add condition judgment for the statement – “PlayFabHttp.instance.OnPlayFabApiResult(reqContainer);” that in the ProcessJsonResponse(CallRequestContainer reqContainer) function .

This modification should prevent SDK initiates OnPlayFabApiResult when the application has been quit. Besides, you can do the further modification for it to perfect the functions.

private static void ProcessJsonResponse(CallRequestContainer reqContainer)
{
......            
	reqContainer.ApiResult.Request = reqContainer.ApiRequest;
               
	reqContainer.ApiResult.CustomData = reqContainer.CustomData;
               
	//Add the condition judgment here.
            
	if (_isApplicationPlaying)
            
	{
           
	PlayFabHttp.instance.OnPlayFabApiResult(reqContainer);
         
	}
         
......

}
1 comment
10 |1200

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

giorgiotino avatar image giorgiotino commented ·

Thanks, I have filed a bug report and I will try to add this workaround

0 Likes 0 ·

Write an Answer

Hint: Notify or tag a user in this post by typing @username.

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.