为什么" SWITCHTO"从异步CTP /发行版中删除? [英] Why was "SwitchTo" removed from Async CTP / Release?

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

问题描述

我试图用SWITCHTO方法今天切换到GUI线程,而且发现我举起它的例子不工作,只是因为该方法是不存在的。

然后我发现这个Blurb的<一个href=\"http://social.msdn.microsoft.com/Forums/en-US/async/thread/078c7e77-5b16-4130-bbf5-c8e6ac82effa\">here:


  

我们摆脱它的原因是因为它是如此危险的。另一种方法是捆扎里面TaskEx.Run ...

您code

我的问题很简单:为什么的是它的危险?将使用它具体有什么危害导致?

请注意,我的没有的阅读帖子的余下部分,让我明白有技术限制在这里。我的问题仍然是,如果我意识到这一点,为什么它的危险的?

我正在考虑重新实现辅助方法给我指定的功能,但如果有什么根本打破,除了有人决定是危险的,我不会做的。

具体,很天真,这里就是我会考虑实施所需的方法:

 公共静态类ContextSwitcher
{
    公共静态ThreadPoolContextSwitcher SwitchToThreadPool()
    {
        返回新ThreadPoolContextSwitcher();
    }    公共静态SynchronizationContextSwitcher SWITCHTO(此的SynchronizationContext的SynchronizationContext)
    {
        返回新SynchronizationContextSwitcher(SynchronizationContext的);
    }
}公共类SynchronizationContextSwitcher:INotifyCompletion
{
    私人只读的SynchronizationContext _SynchronizationContext;    公共SynchronizationContextSwitcher(的SynchronizationContext的SynchronizationContext)
    {
        _SynchronizationContext = SynchronizationContext的;
    }    公共SynchronizationContextSwitcher GetAwaiter()
    {
        返回此;
    }    公共BOOL IsCompleted
    {
        得到
        {
            返回false;
        }
    }    公共无效OnCompleted(动作动作)
    {
        _SynchronizationContext.Post(_ =&GT;动作(),NULL);
    }    公共无效调用getResult()
    {
    }
}公共类ThreadPoolContextSwitcher:INotifyCompletion
{
    公共ThreadPoolContextSwitcher GetAwaiter()
    {
        返回此;
    }    公共BOOL IsCompleted
    {
        得到
        {
            返回false;
        }
    }    公共无效OnCompleted(动作动作)
    {
        ThreadPool.QueueUserWorkItem(_ =&GT;动作(),NULL);
    }    公共无效调用getResult()
    {
    }
}

这将让我写code是这样的:

 公共异步无效测试()
{
    等待ContextSwitcher.SwitchToThreadPool(); //确保我们不会陷入泥淖UI线程
    //做一些繁重的处理
    等待_UIContext.SwitchTo(); // presumably主线程保存
    //用新的数据更新的用户界面
}


解决方案

斯蒂芬Toub对在<一个推理一些更多的信息href=\"http://social.msdn.microsoft.com/Forums/en-US/async/thread/642ffef6-d3ce-4010-978d-bc5d8b65c00f\"相对=nofollow>此线程。

要总结,这不是有两个原因一个好主意:


  1. 它促进非结构化code。如果你有重处理,你需要做的,它应该被放置在一个 Task.Run 。更妙的是,从你的UI逻辑中分离出来的业务逻辑。

  2. 错误处理,并在一个未知的环境中运行(一般般)延续。 / 最后试块需要处理运行在一个线程池的的UI环境(如果他们在线程池上下文中运行,他们不能使用 SWITCHTO 来跳上UI上下文)。另外,只要你等待返回工作你应该确定(的await 将纠正,如果必要的延续上下文中),但是如果你有使用明确的 ContinueWith 延续 ExecuteSynchronously ,那么他们就会有相同的问题,因为 / 最后块。

总之,code是更清洁和更predictable没有 SWITCHTO

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.

I then found this 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...

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 has some more information on the reasoning in this thread.

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

  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.

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

这篇关于为什么&QUOT; SWITCHTO&QUOT;从异步CTP /发行版中删除?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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