提问人:Daniel 提问时间:1/19/2023 更新时间:1/19/2023 访问量:147
等待具有超时的单个事件
Waiting for single event with timeout
问:
我当前的解决方案需要一个全局 CancellationTokenSource 类。没有它也可以做同样的事情吗?
CancellationTokenSource _waitCTS = null;
private async Task WaitWithTimeout(string param)
{
_waitCTS?.Dispose();
_waitCTS = new CancellationTokenSource();
XClass x = new XClass(param);
x.OnReceived += X_OnReceived;
try
{
await Task.Delay(5000, _waitCTS.Token).ConfigureAwait(true);
}
catch (TaskCanceledException)
{
Debug.WriteLine("Timed out");
}
x.OnReceived -= X_OnReceived;
x.Cleanup();
}
private void X_OnReceived(object sender, SelectedItemEventArgs e)
{
Debug.WriteLine(e.ReceivedItem);
if (_waitCTS != null)
_waitCTS.Cancel();
}
答:
2赞
David Browne - Microsoft
1/19/2023
#1
可以使处理程序成为捕获 CancellationTokenSource 变量的本地处理程序。例如:
private async Task WaitWithTimeout(string param)
{
var CancellationTokenSource _waitCTS = new CancellationTokenSource();
XClass x = new XClass(param);
SelectedItemEventHandler X_OnReceived = (s, e) =>
{
Debug.WriteLine(e.ReceivedItem);
_waitCTS.Cancel();
}
x.OnReceived += X_OnReceived;
try
{
await Task.Delay(5000, _waitCTS.Token).ConfigureAwait(true);
}
catch (TaskCanceledException)
{
Debug.WriteLine("Timed out");
}
x.OnReceived -= X_OnReceived;
x.Cleanup();
}
2赞
Evk
1/19/2023
#2
你可以完全不做,例如:CancellationTokenSource
TaskCompletionSource
async Task WaitWithTimeout()
{
var tcs = new TaskCompletionSource<string>();
XClass x = new XClass();
// declare handler as local variable here
Action<string> handler = (s) =>
{
// complete the task
tcs.TrySetResult(s);
};
x.OnReceived += handler;
// now check which task completes first - the one from handler, or delay 5s
var completedFirst = await Task.WhenAny(tcs.Task, Task.Delay(5000));
x.OnReceived -= handler;
if (completedFirst == tcs.Task)
{
// got the result here
Console.WriteLine(tcs.Task.Result);
}
else
{
Console.WriteLine("Timed out");
}
}
class XClass
{
public event Action<string> OnReceived;
}
评论