简体   繁体   中英

C# - Does calling Task.Result wait until result is returned before returning

Here is my code:

public void ConnectToWorldServer()
{
    if (socketReady)
    {
        return;
    }
    //Default host and port values;
    string host = ClientWorldServer.ServerIP;
    int port = ClientWorldServer.TCPPort;

    //ClientLoginServer ClientLoginServer = new ClientLoginServer();


    try
    {

        socket = new TcpClient(host, port);
        stream = socket.GetStream();
        socket.NoDelay = true;
        writer = new StreamWriter(stream);
        reader = new StreamReader(stream);
        socketReady = true;
        //Preserve the connection to worldserver thrue scenes
        UnityThread.executeInUpdate(() =>
        {
            DontDestroyOnLoad(worldserverConnection);
        });

        // Start listening for connections.
        while (true)
        {
            if (socketReady)
            {
                if (stream.DataAvailable)
                {
                    string sdata = reader.ReadLine();
                    if (sdata != null)
                    {

                        Task<JsonData> jsonConvert = Task<JsonData>.Factory.StartNew(() => convertJson(sdata));
                        UnityThread.executeInUpdate(() =>
                        {
                            OnIncomingData(jsonConvert.Result);
                        });
                    }
                }
            }
        }
    }
    catch (Exception e)
    {
        Debug.Log("Socket error : " + e.Message);
    }

}

private JsonData convertJson(string data)
{
    return JsonConvert.DeserializeObject<JsonData>(data);    
}

What I am wondering now is does this part of the code:

UnityThread.executeInUpdate(() =>
{
    OnIncomingData(jsonConvert.Result);
});

block until this task returns back a result:

Task<JsonData> jsonConvert = Task<JsonData>.Factory.StartNew(() => convertJson(sdata));

I am really not that familiar with Tasks. My goal is to run the json conversion and then execute OnIncomingData(jsonConvert.Result); .

I think my code is not doing that. Why?

When a thread invokes Task.Result it will block until the Task completes, either by returning a value, throwing an exception, or being canceled. From the documentation :

Accessing the property's get accessor blocks the calling thread until the asynchronous operation is complete; it is equivalent to calling the Wait method.

So, to be clear, calling Task<JsonData>.Factory.StartNew creates a Task (which represents some computation to be executed), and schedules it for execution (when it gets executed and on what thread is up to the default TaskScheduler , but StartNew should return immediately). Your call to UnityThread.executeInUpdate will then happen without waiting for the Task you created to complete. At the point where UnityThread calls the anonymous function you passed to executeInUpdate that thread will block until the Task completes. I'm not familiar with UnityThread.executeInUpdate so I cannot tell you whether it will block until that callback completes or not.

One thing to be aware of is that depending on how Unity works with threads, it is possible to create a deadlock by accessing the Result property. In some cases a Task will attempt to use a specific context to execute, and if you cause that context to block waiting for the Task to complete, it will never get a chance to run: https://blog.stephencleary.com/2012/07/dont-block-on-async-code.html

If you want to wait for the result then what is the point of using the Task . The right way of doing thing asynchronously is making your function async all the way.

public async void ConnectToWorldServer()
{
   .....
   .....
// Here await will put this method call on a queue to finish later and will return from this method. 
         Task<JsonData> jsonConvert = await Task<JsonData>.Factory.StartNew(() => convertJson(sdata));
// After the task is finished, it will resume to this method here to execute next statement. 
         UnityThread.executeInUpdate(() =>
         {
            OnIncomingData(jsonConvert.Result);
         });
   .....
   .....
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM