C# 如何确保在单个线程中执行可等待的操作

C# How can I make sure to execute awaitable operations in a single thread

我正在构建一个 UWP 应用程序,其中显然包含对异步方法的多个等待调用。

在其中一个事件处理程序中,我需要确保调用链是在单个线程中执行的。

我试图通过等待并获取结果来制作我需要的 "sync" 版本的异步方法,如下所示:

public static T Sync<T>(this Task<T> task)
{
    if (task == null)
        return default(T);
    return task.ConfigureAwait(false).GetAwaiter().GetResult();
}

或者更残酷:

    public static T Sync<T>(this Task<T> task)
    {
        if (task == null)
            return default(T);
        task.Wait();
        return task.Result;
    }

但是我遇到了其他几个博客中描述的死锁问题,因为我 运行 在 UI 线程上。

有什么方法可以实现我的目标吗?

如果您只关心序列化对状态的访问(即您一次只希望一个线程修改状态),您可以使用 .NET 中内置的众多同步原语之一来实现这一点。

最简单的工具之一是 lock 语句。

当然这会产生阻塞您的 Task 的副作用,这可能不适合您的应用程序。但是 "async" locks.

有一些可用的实现

How can I make sure to execute awaitable operations in a single thread

正如其他人指出的那样,默认情况下 UI 线程上的 async/await 在单个线程上执行所有延续。

I want to avoid that while I am awaiting, another async call changes my state.

正确的解决方案是修正你的逻辑。任何替代方案 - 特别是使 UI 线程无响应 - 都会降低您的用户体验,并可能阻止您的应用程序在商店中被接受。

就是说,如果您绝对确定您想沿着这条路走下去而不是首先修复您的代码,您有两个主要选择:

  1. 使所有代码同步。它会 运行 在 UI 线程上并根据需要阻止它。
  2. 运行 一个嵌套的消息循环。我不确定 UWP 是否支持此功能;你 可能 可以使用我的 AsyncContext.
  3. 让一些东西工作

同样,这两种 这些解决方案都会使您的 UI 无响应,降低您的用户体验并可能导致商店拒绝。