在断开连接的情况下将同步代码包装到异步等待中
Wrap synchronous code into async await in disconnected scenario
我有以下客户端-服务器风格的伪代码:
public void GetGrades() {
var msg = new Message(...); // request in here
QueueRequest?.Invoke(this, msg); // add to outgoing queue
}
在另一个处理器中 class 我有一个循环 :
// check for messages back from server
// server response could be a "wait", if so, wait for real response
// raise MessageReceived event here
// each message is then processed by classes which catch the event
// send new messages to server
if (queue.Any()){
var msg = queue.Dequeue();
// send to server over HTTP
}
我已经大大简化了这段代码,因此很容易看出我的问题的目的。
目前我这样称呼这段代码:
student.GetGrades(); // fire and forget, almost
但是我知道结果何时返回的方式不太理想,我基本上使用事件:
我提高 MessageReceived?.Invoke(this, msg);
然后在另一个级别捕获它 StudentManager
将结果设置在特定的学生对象上。
但是我想把它包装在 async await
中,并有类似这样的东西:
var grades = await GetGrades();
在这种断开连接的情况下这可能吗?我该怎么做?
您可以尝试使用 TaskCompletionSource。你可以这样做
TaskCompletionSource<bool> _tcs;
public Task GetGrades() {
var msg = new Message(...); // request in here
QueueRequest?.Invoke(this, msg); // add to outgoing queue
_tcs = new TaskCompletionSource<bool>();
return _tcs;
}
然后当您需要确认任务是否已完成时,您就可以了。
_tcs.TrySetResult(true);
通过这样做你可以做到:
var grades = await GetGrades();
当然这里还有另外的事情要解决。如果可以多次调用,您将把那些 TaskCompletionSource
保存在哪里,以及如何 link 每条消息发送给每个 TaskCompletionSource
。但我希望你能理解基本的想法。
我有以下客户端-服务器风格的伪代码:
public void GetGrades() {
var msg = new Message(...); // request in here
QueueRequest?.Invoke(this, msg); // add to outgoing queue
}
在另一个处理器中 class 我有一个循环 :
// check for messages back from server
// server response could be a "wait", if so, wait for real response
// raise MessageReceived event here
// each message is then processed by classes which catch the event
// send new messages to server
if (queue.Any()){
var msg = queue.Dequeue();
// send to server over HTTP
}
我已经大大简化了这段代码,因此很容易看出我的问题的目的。
目前我这样称呼这段代码:
student.GetGrades(); // fire and forget, almost
但是我知道结果何时返回的方式不太理想,我基本上使用事件:
我提高 MessageReceived?.Invoke(this, msg);
然后在另一个级别捕获它 StudentManager
将结果设置在特定的学生对象上。
但是我想把它包装在 async await
中,并有类似这样的东西:
var grades = await GetGrades();
在这种断开连接的情况下这可能吗?我该怎么做?
您可以尝试使用 TaskCompletionSource。你可以这样做
TaskCompletionSource<bool> _tcs;
public Task GetGrades() {
var msg = new Message(...); // request in here
QueueRequest?.Invoke(this, msg); // add to outgoing queue
_tcs = new TaskCompletionSource<bool>();
return _tcs;
}
然后当您需要确认任务是否已完成时,您就可以了。
_tcs.TrySetResult(true);
通过这样做你可以做到:
var grades = await GetGrades();
当然这里还有另外的事情要解决。如果可以多次调用,您将把那些 TaskCompletionSource
保存在哪里,以及如何 link 每条消息发送给每个 TaskCompletionSource
。但我希望你能理解基本的想法。