gpt4 book ai didi

c# - 防止事件处理程序中 InvokeRequired 的必要性

转载 作者:行者123 更新时间:2023-12-03 13:19:52 25 4
gpt4 key购买 nike

我一直在编写一个 API 来促进与串行端口的通信。我正在进行一些重构和一般清理,想知道是否有办法避免以下问题。

API 中的主类能够不断从端口读取数据,并在读取字节与特定正则表达式匹配时引发包含值的事件。读取和解析的过程发生在另一个线程上。该事件包含作为参数 (string) 的值,并且因为它是从另一个线程引发的,所以客户端试图直接将值分配给 除非处理程序具有正确的 Invoke 代码,否则控件的 Text 属性会导致跨线程异常。

我理解为什么会发生这种情况,当我将正确的调用代码放入测试客户端的事件处理程序时,一切都很好;我的问题是我是否可以在 API 代码本身中做任何事情,以便客户不必担心它。

基本上,我想把这个:

void PortAdapter_ValueChanged(Command command, string value)
{
if (this.InvokeRequired)
{
Invoke(new MethodInvoker(() =>
{
receivedTextBox.Text = value;
}));
}
else
{
receivedTextBox.Text = value;
}
}

简单地说:

void PortAdapter_ValueChanged(Command command, string value)
{
receivedTextBox.Text = value;
}

最佳答案

嗯,在 .Net 框架本身的许多地方使用了一个通用模式。例如 BackgroundWorker 使用此模型。

为此,您将使用 SynchronizationContext 作为 API 的参数,在本例中我假设它是 PortAdapter

引发事件时,您可以使用 SynchronizationContext.PostSynchronizationContext.Send 在给定的 SynchronizationContext 中引发事件。前者是异步的,后者是同步的。

因此,当客户端代码创建您的 PortAdapter 实例时,它会将 WindowsFormsSynchronizationContext 实例作为参数传递。这意味着 PortAdapter 将在给定的同步上下文中引发事件,这也意味着您不需要 InvokeRequiredInvoke 调用。

public class PortAdapter
{
public event EventHandler SomethingHappened;

private readonly SynchronizationContext context;
public PortAdapter(SynchronizationContext context)
{
this.context = context ?? new SynchronizationContext();//If no context use thread pool
}

private void DoSomethingInteresting()
{
//Do something

EventHandler handler = SomethingHappened;
if (handler != null)
{
//Raise the event in client's context so that client doesn't needs Invoke
context.Post(x => handler(this, EventArgs.Empty), null);
}
}
}

客户端代码:

PortAdapter adpater = new PortAdapter(SynchronizationContext.Current);
...

在 UI 线程中创建 PortAdapter 的实例非常重要,否则 SynchronizationContext.Current 将为 null,因此事件仍将在 ThreadPool 线程中引发。

More about SynchronizationContext here.

关于c# - 防止事件处理程序中 InvokeRequired 的必要性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26343132/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com