SynchronizationContext 有什么作用? [英] What does SynchronizationContext do?

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

问题描述

在Programming C#一书中,有一些关于SynchronizationContext的示例代码:

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

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

我是线程的初学者,所以请详细回答.首先,我不知道context是什么意思,程序在originalContext中保存了什么?当 Post 方法被触发时,UI 线程会做什么?
如果我问了一些愚蠢的事情,请纠正我,谢谢!

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!

例如,如果我在方法中只写myTextBox.Text = text;,有什么区别?

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

推荐答案

SynchronizationContext 有什么作用?

简单地说,SynchronizationContext 表示位置where"代码可能会被执行.传递到其 SendPost 方法 将在该位置被调用.(PostSend 的非阻塞/异步版本.)

Simply put, SynchronizationContext represents a location "where" code might be executed. Delegates that are passed to its Send or Post method will then be invoked in that location. (Post is the non-blocking / asynchronous version of Send.)

每个线程都可以有一个与之关联的 SynchronizationContext 实例.通过调用 静态SynchronizationContext.SetSynchronizationContext 方法,可以通过SynchronizationContext.Current 属性.

Every thread can have a SynchronizationContext instance associated with it. The running thread can be 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.

尽管我刚刚写了什么(每个线程都有一个关联的同步上下文),SynchronizationContext 不一定代表一个特定线程;它还可以将传递给它的委托的调用转发到多个线程中的任何一个(例如到 ThreadPool 工作线程),或(至少在理论上)到特定的CPU 内核,甚至到另一个网络主机.您的代表最终运行的位置取决于所使用的 SynchronizationContext 类型.

Despite what I just wrote (each thread having an 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) to a specific CPU core, or even to another network host. Where your delegates end up running is dependent on the type of SynchronizationContext used.

Windows 窗体将在创建第一个窗体的线程上安装 WindowsFormsSynchronizationContext.(这个线程通常被称为UI线程".)这种类型的同步上下文调用正是在那个线程上传递给它的委托.这非常有用,因为与许多其他 UI 框架一样,Windows 窗体只允许在创建控件的同一线程上操作控件.

Windows Forms will install a WindowsFormsSynchronizationContext on the thread on which the first form is created. (This thread is commonly called "the UI thread".) 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.

如果我只在方法中写myTextBox.Text = text;,有什么区别?

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

您传递给ThreadPool.QueueUserWorkItem 将在线程池工作线程上运行.也就是说,它不会在创建您的 myTextBox 的线程上执行,因此 Windows 窗体迟早会(尤其是在发布版本中)抛出异常,告诉您您可能无法访问 myTextBox 来自另一个线程.

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 Forms will sooner or later (especially in Release builds) throw an exception, telling you that you may not access myTextBox from across another thread.

这就是为什么你必须以某种方式切换回来";从工作线程到UI线程"(其中创建了 myTextBox)在该特定分配之前.这是按如下方式完成的:

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

  1. 当您仍在 UI 线程上时,在那里捕获 Windows 窗体的 SynchronizationContext,并将对其的引用存储在变量 (originalContext) 中以备后用用.此时必须查询SynchronizationContext.Current;如果您在传递给 ThreadPool.QueueUserWorkItem 的代码中查询它,您可能会得到与线程池的工作线程相关联的任何同步上下文.一旦您存储了对 Windows 窗体上下文的引用,您就可以随时随地使用它来发送"窗口.代码到 UI 线程.

  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.

每当您需要操作 UI 元素时(但不再或可能不再在 UI 线程上),请通过 originalContext 访问 Windows 窗体的同步上下文,然后移交将操纵 UI 以SendPost 的代码.

Whenever you need to manipulate a UI element (but are not, or might not be, 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.


最后的评论和提示:

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