我今天尝试使用SwitchTo方法切换到GUI线程,并发现我将其解除的示例不起作用,因为该方法不存在.
然后我发现这个blurb here:
The reason we got rid of it was because it was so dangerous. The alternative is to bundle up your code inside TaskEx.Run…
我的问题是简单的:为什么是危险的?使用什么特定的危险会导致?
请注意,我已经阅读了其余的帖子,所以我明白这里有技术上的限制.我的问题是,如果我知道这一点,为什么会很危险?
我正在考虑重新执行帮助方法给我指定的功能,但如果有一些根本的破坏,除了有人认为这是危险的,我不会这样做.
具体来说,非常天真,我将如何考虑实现所需的方法:
public static class ContextSwitcher { public static ThreadPoolContextSwitcher SwitchToThreadPool() { return new ThreadPoolContextSwitcher(); } public static SynchronizationContextSwitcher SwitchTo(this SynchronizationContext synchronizationContext) { return new SynchronizationContextSwitcher(synchronizationContext); } } public class SynchronizationContextSwitcher : INotifyCompletion { private readonly SynchronizationContext _SynchronizationContext; public SynchronizationContextSwitcher(SynchronizationContext synchronizationContext) { _SynchronizationContext = synchronizationContext; } public SynchronizationContextSwitcher GetAwaiter() { return this; } public bool IsCompleted { get { return false; } } public void OnCompleted(Action action) { _SynchronizationContext.Post(_ => action(),null); } public void GetResult() { } } public class ThreadPoolContextSwitcher : INotifyCompletion { public ThreadPoolContextSwitcher GetAwaiter() { return this; } public bool IsCompleted { get { return false; } } public void OnCompleted(Action action) { ThreadPool.QueueUserWorkItem(_ => action(),null); } public void GetResult() { } }
这将允许我编写如下代码:
public async void Test() { await ContextSwitcher.SwitchToThreadPool(); // ensure we're not bogging down the UI thread // do some heavy processing await _UIContext.SwitchTo(); // presumably saved from the main thread // update UI with new data }
解决方法
Stephen Toub在
this thread年有更多关于推理的信息.
总而言之,这不是一个好主意,有两个原因:
>它促进非结构化代码.如果你需要“重加工”,那么应该放在Task.Run中.更好的是将您的业务逻辑与UI逻辑分开.
>错误处理和(某些)连续运行在未知的上下文中.测试中的catch / finally块将需要处理线程池或UI上下文中的运行(如果它们在线程池上下文中运行,则不能使用SwitchTo跳转到UI上下文).此外,只要你等待返回的任务,你应该是OK(等待将修正继续上下文,如果需要),但是如果您有明确的ContinueWith连续使用ExecuteSynchronously,那么他们将有与catch / finally块相同的问题.
简而言之,如果没有SwitchTo,代码更清晰,更可预测.