同步可中断等待

本文关键字:等待 中断 同步 | 更新日期: 2023-09-27 18:34:43

在 ASP.NET C#页面上,我有一个需要执行的异步initialAction

initialAction涉及服务器通过 WebSocket 发送消息,服务器应等待一段时间,直到客户端响应。 一旦它响应,它应该调用onComplete。 我已经完成了这部分。

如果操作未在 5 秒内完成其工作(例如(,我希望脚本继续。 目前,我通过反复睡眠和检查CancellationTokenSource来使脚本在任务中等待。 如果CancellationTokenSource被取消onComplete或者已经过去了 5 秒,脚本将继续。

以下是我找到的最好的方法。 有没有更好的方法?

public static string wait(Action<Action<string>> initialAction)
{
    string message = null;
    using (CancellationTokenSource tokenSource = new CancellationTokenSource())
    {
        Action<string> onComplete = (msg) =>
        {
            message = msg;
            tokenSource.Cancel();
        };
        Task sleepTask = new Task(() =>
        {
            Stopwatch stopwatch = Stopwatch.StartNew();
            while (true)
            {
                if (tokenSource.IsCancellationRequested ||
                    stopwatch.ElapsedMilliseconds > 5000) { break; }
                Thread.Sleep(10);
            }
        }, tokenSource.Token);
        initialAction(onComplete);
        sleepTask.Start();
        sleepTask.Wait();
    }
    return message;
}

同步可中断等待

这比你想象的要容易得多。 首先,只需将超时放入取消令牌源的构造函数中,使其在一段时间后超时。

然后,要等到令牌被取消,只需抓住令牌的等待句柄并等待它,而不是创建一个任务来对其执行旋转等待。

public static string wait(Action<Action<string>> initialAction)
{
    string message = null;
    using (CancellationTokenSource tokenSource = new CancellationTokenSource(5000))
    {
        initialAction(msg =>
        {
            message = msg;
            tokenSource.Cancel();
        });
        tokenSource.Token.WaitHandle.WaitOne();
    }
    return message;
}

请注意,在两个代码片段中,"中止"操作仍在继续;它没有停止,我们只是停止等待它并返回null