为什么是“切换到"?从异步 CTP/Release 中删除? [英] Why was "SwitchTo" removed from Async CTP / Release?

查看:42
本文介绍了为什么是“切换到"?从异步 CTP/Release 中删除?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我今天尝试使用SwitchTo方法切换到GUI线程,发现我举的例子不起作用,只是因为没有该方法.

I tried to use the SwitchTo method today to switch to the GUI thread, and found that the example I lifted it from does not work, simply because the method is not there.

然后我在这里找到了这个简介:

我们摆脱它的原因是因为它太危险了.另一种方法是将您的代码捆绑到 TaskEx.Run...

The reason we got rid of it was because it was so dangerous. The alternative is to bundle up your code inside TaskEx.Run...

我的问题很简单:为什么很危险?使用它会导致哪些具体的危险?

My question is simply: Why was it dangerous? What specific dangers would using it lead to?

请注意,我确实阅读了该帖子的其余部分,因此我确实理解此处存在技术限制.我的问题仍然是,如果我知道这一点,为什么它危险?

Note that I did read the rest of that post, so I do understand there are technical limitations here. My question is still, if I'm aware of this, why is it dangerous?

我正在考虑重新实现辅助方法来为我提供指定的功能,但如果有什么根本性的问题,除了有人认为它是危险的,我不会这样做.

I am considering reimplementing helper methods to give me the specified functionality, but if there is something fundamentally broken, other than that someone decided it was dangerous, I would not do it.

具体来说,非常天真,以下是我考虑实现所需方法的方式:

Specifically, very naively, here's how I would consider implementing the required methods:

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()
    {
    }
}

这将允许我编写这样的代码:

This would allow me to write code like this:

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 在 这个线程.

Stephen Toub has some more information on the reasoning in this thread.

总而言之,这不是一个好主意,原因有两个:

To summarize, it's not a good idea for two reasons:

  1. 它提倡非结构化代码.如果您需要进行繁重的处理",则应将其放置在 Task.Run 中.更好的是,将业务逻辑与 UI 逻辑分开.
  2. 错误处理和(某些)延续在未知上下文中运行.catch/finally Test 中的块需要处理线程池 UI 上下文中的运行(如果它们'在线程池上下文中运行,它们不能使用 SwitchTo 跳转到 UI 上下文).另外,只要你 await 返回的 Task 你应该没问题(await 将在必要时更正继续上下文),但如果你有使用 ExecuteSynchronously 的显式 ContinueWith 延续,那么它们将遇到与 catch/finally 块相同的问题.
  1. It promotes unstructured code. If you have "heavy processing" that you need to do, it should be placed in a Task.Run. Even better, separate your business logic from your UI logic.
  2. Error handling and (some) continuations run in an unknown context. catch/finally blocks in Test would need to handle running in a thread pool or UI context (and if they're running in the thread pool context, they can't use SwitchTo to jump on the UI context). Also, as long as you await the returned Task you should be OK (await will correct the continuation context if necessary), but if you have explicit ContinueWith continuations that use ExecuteSynchronously, then they'll have the same problem as the catch/finally blocks.

简而言之,没有SwitchTo,代码更简洁、更可预测.

In short, the code is cleaner and more predictable without SwitchTo.

这篇关于为什么是“切换到"?从异步 CTP/Release 中删除?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆