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

时间:2019-01-28 17:06:29

标签: c# multithreading uwp async-await deadlock

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

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

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

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线程上运行。

有没有办法实现我的目标?

2 个答案:

答案 0 :(得分:0)

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

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

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

答案 1 :(得分:0)

  

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

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

  

我想避免在等待时避免另一个异步调用更改我的状态。

正确的 解决方案是修复您的逻辑。任何其他选择(尤其是使UI线程不响应)都会降低用户体验,并可能阻止应用在商店中被接受。

也就是说,如果您完全确定要走那条路,而不是首先固定代码,则有两个主要选择:

  1. 使所有代码同步。它将在UI线程上运行并根据需要阻止它。
  2. 运行一个嵌套的消息循环。我不确定UWP是否支持此功能;您可能可以使用我的AsyncContext正常工作。
同样,这些解决方案的

两者都会使您的UI无响应,从而降低用户体验并可能导致商店拒绝。