更新时间:2022-04-28 21:54:14
您似乎了解问题所涉及的风险,所以我将跳过讲座.
It seems you understand the risks involved in your question so I'll skip the lecture.
要回答您的实际问题:是的,您可以使用 Task.Run
将该工作卸载到没有 SynchronizationContext 的
所以没有真正的死锁风险.ThreadPool
线程
To answer your actual question: Yes, you can just use Task.Run
to offload that work to a ThreadPool
thread which doesn't have a SynchronizationContext
and so there's no real risk for a deadlock.
但是,仅仅因为没有 SC 就使用另一个线程是一种黑客行为,并且可能会很昂贵,因为在 ThreadPool
上安排要完成的工作它的成本.
However, using another thread just because it has no SC is somewhat of a hack and could be an expensive one since scheduling that work to be done on the ThreadPool
has its costs.
IMO 更好、更清晰的解决方案是暂时使用 SynchronizationContext.SetSynchronizationContext
移除 SC,然后再恢复.这可以很容易地封装到 IDisposable
中,以便您可以在 using
范围内使用它:
A better and clearer solution IMO would be to simply remove the SC for the time being using SynchronizationContext.SetSynchronizationContext
and restoring it afterwards. This can easily be encapsulated into an IDisposable
so you can use it in a using
scope:
public static class NoSynchronizationContextScope
{
public static Disposable Enter()
{
var context = SynchronizationContext.Current;
SynchronizationContext.SetSynchronizationContext(null);
return new Disposable(context);
}
public struct Disposable : IDisposable
{
private readonly SynchronizationContext _synchronizationContext;
public Disposable(SynchronizationContext synchronizationContext)
{
_synchronizationContext = synchronizationContext;
}
public void Dispose() =>
SynchronizationContext.SetSynchronizationContext(_synchronizationContext);
}
}
用法:
private void MySynchronousMethodLikeDisposeForExample()
{
using (NoSynchronizationContextScope.Enter())
{
MyAsyncMethod().Wait();
}
}