这是什么做的SynchronizationContext? [英] What does SynchronizationContext do?

查看:143
本文介绍了这是什么做的SynchronizationContext?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在这本书编程C#,它有一些样品code约的SynchronizationContext

 的SynchronizationContext originalContext = SynchronizationContext.Current;
ThreadPool.QueueUserWorkItem(委托{
    字符串文本= File.ReadAllText(@C:\ TEMP \ log.txt的);
    originalContext.Post(委托{
        myTextBox.Text =文本;
    }, 空值);
});
 

我在线程初学者,所以请详细回答。 首先,我不知道是什么意思背景下,什么是程序保存在 originalContext ?而当发表方法被激发,会出现什么UI线程呢?
如果我问一些无聊的事,请大家指正,谢谢!

编辑:例如,如果我只是写什么 myTextBox.Text =文本; 的方法,有什么区别

解决方案
  

什么的SynchronizationContext办?

在它的核心,的SynchronizationContext 是一个位置,其中code可能会被执行的只是一个再presentation。被传递给代表其发送发表方法,然后在该位置调用。

每个线程都可以有它自己携带的的SynchronizationContext 实例。线程与同步上下文通​​过调用相关的<一个href="http://msdn.microsoft.com/en-us/library/system.threading.synchronizationcontext.setsynchronizationcontext.aspx">static SynchronizationContext.SetSynchronizationContext 方法和正在运行的线程的当前上下文可以通过<一个查询href="http://msdn.microsoft.com/en-us/library/system.threading.synchronizationcontext.current.aspx"><$c$c>SynchronizationContext.Current物业。

  

<分> 边注:尽管我刚才说的(有一个相关的同步上下文中的每个线程),一个的SynchronizationContext 不一定再present一个的特定线程的;它可以传递给它的任意几个的线程代表还向前调用(比如一个<一个href="http://msdn.microsoft.com/en-us/library/system.threading.threadpool.aspx"><$c$c>ThreadPool工作线程),或(至少在理论上)它甚至可以向前代表调用给一个特定的 CPU核心的,或到另一个的网络主机的。当您的代表最终的运行依赖于类型的SynchronizationContext 使用。

Windows窗体将在其中创建第一个窗体的线程上安装一个 WindowsFormsSynchronizationContext 。这种类型的同步上下文的调用传递给它的正是线的代表。这是因为Windows窗体非常有用的,像许多其他的UI框架,只允许其创建的同一线程操作的控制。

  

如果我只是写 myTextBox.Text =文本; 的方法,有什么区别

您已经传递给 ThreadPool.QueueUserWorkItem 的code将在一个线程池工作线程中运行。也就是说,它不会在线程上执行上的 myTextBox 创建的,所以Windows窗体迟早会抛出一个异常,告诉你不能访问 myTextBox 来自全国各地的另一个主题。

这就是为什么你必须以某种方式从工作线程切换到UI线程(其中 myTextBox 创建)。这样做是如下:

  1. 虽然你还是在UI线程上,捕获Windows窗体的SynchronizationContext 那里,存储对它的引用在变量( originalContext )以备后用。你必须查询 SynchronizationContext.Current 在这一点上,如果你里面传递给 ThreadPool.QueueUserWorkItem 的code质疑它,你可能会得到什么同步上下文与线程池的工作线程关联。一旦你存储一个参考Windows窗体的背景下,你可以用它在任何地方和任何时间,以送code到UI线程。

  2. 每当你需要操纵UI元素(但不是在UI线程上了),通过 originalContext 访问Windows窗体同步上下文,和挂断在code,将操作界面为发送发表

  

<分> 最后说明:什么同步上下文的不会的为你做的是告诉你什么code必须在特定的位置/环境下运行,并什么code正好可以正常执行,而不将它传递给一个的SynchronizationContext 。为了决定,你必须知道的规则,你对编程&mdash框架的要求;视窗形式在这种情况下。

     

<子>所以请记住Windows窗体这个简单的规则:不要从一个线程比创建它们的另外一个访问控制或形式。如果你必须这样做,使用的SynchronizationContext 机制,或者的 Control.BeginInvoke (这是在做同样的事情的Windows窗体特定的方式)。

In the book Programming C#, it has some sample code about SynchronizationContext:

SynchronizationContext originalContext = SynchronizationContext.Current;
ThreadPool.QueueUserWorkItem(delegate {
    string text = File.ReadAllText(@"c:\temp\log.txt");
    originalContext.Post(delegate {
        myTextBox.Text = text;
    }, null);
});

I'm a beginner in threads, so please answer in detail. First, I don't know what does context mean, what does the program save in the originalContext? And when the Post method is fired, what will the UI thread do?
If I ask some silly things, please correct me, thanks!

EDIT: For example, what if I just write myTextBox.Text = text; in the method, what's the difference?

解决方案

What does SynchronizationContext do?

At its core, SynchronizationContext is simply a representation of a location "where" code might be executed. Delegates that are passed to its Send or Post method will then be invoked in that location.

Every thread can have its own SynchronizationContext instance associated with it. A thread is associated with a synchronization context by calling the static SynchronizationContext.SetSynchronizationContext method, and the current context of the running thread can be queried via the SynchronizationContext.Current property.

Side note: Despite what I just said (each thread having a associated synchronization context), a SynchronizationContext does not necessarily represent a specific thread; it can also forward invocation of the delegates passed to it to any of several threads (e.g. to a ThreadPool worker thread), or (at least in theory) it could even forward delegate invocation to a specific CPU core, or to another network host. Where your delegates end up running is dependent on the type of SynchronizationContext used.

Windows Forms will install a WindowsFormsSynchronizationContext on the thread on which the first form is created. This type of synchronization context invokes the delegates passed to it on exactly that thread. This is very useful since Windows Forms, like many other UI frameworks, only permits manipulation of controls on the same thread on which they were created.

What if I just write myTextBox.Text = text; in the method, what's the difference?

The code that you've passed to ThreadPool.QueueUserWorkItem will be run on a thread pool worker thread. That is, it will not execute on the thread on which your myTextBox was created, so Windows Form will sooner or later throw an exception, telling you may not access myTextBox from across another thread.

This is why you have to somehow "switch back" from the worker thread to the "UI thread" (where myTextBox was created). This is done as follows:

  1. While you are still on the UI thread, capture Windows Forms' SynchronizationContext there, and store a reference to it in a variable (originalContext) for later use. You must query SynchronizationContext.Current at this point; if you queried it inside the code passed to ThreadPool.QueueUserWorkItem, you might get whatever synchronization context is associated with the thread pool's worker thread. Once you have stored a reference to Windows Forms' context, you can use it anywhere and at any time to "send" code to the UI thread.

  2. Whenever you need to manipulate a UI element (but are not on the UI thread anymore), access Windows Forms' synchronization context via originalContext, and hand off the code that will manipulate the UI to either Send or Post.

Final note: What synchronization contexts won't do for you is telling you what code must run in a specific location / context, and what code can just be executed normally, without passing it to a SynchronizationContext. In order to decide that, you must know the rules and requirements of the framework you're programming against — Windows Forms in this case.

So remember this simple rule for Windows Forms: DO NOT access controls or forms from a thread other than the one that created them. If you must do this, use the SynchronizationContext mechanism, or Control.BeginInvoke (which is a Windows Forms-specific way of doing exactly the same thing).

这篇关于这是什么做的SynchronizationContext?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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