Reputation: 3308
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?
Upvotes: 0
Views: 110
Reputation: 14677
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);
});
.....
.....
}
Upvotes: 1
Reputation: 20150
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
Upvotes: 1