gpt4 book ai didi

c# - 通用 BeginInvoke Scheme 以确保在同一线程上下文中调用函数

转载 作者:行者123 更新时间:2023-11-30 22:05:26 24 4
gpt4 key购买 nike

我正在将一些代码从 winforms 控制对象移动到一个单独的对象,以实现更好的模块化。但是,有一些对外部对象发出回调的调用,我无法控制这些回调,并且可以从作为主 UI 线程的不同线程触发。为避免这种情况,我使用众所周知的 BeginInvoke 方案来检查是否应将调用转移到主 UI 线程。

当我现在将此代码移动到我的分离对象时,我不再需要 Winforms 引用。我可以处理一个 Control 对象,以确保一切都在同一个线程中运行。但我宁愿有一个通用机制,它的功能与确保 Threadconext 完全相同,例如创建对象或调用特定入口函数也用于后续发出的调用,例如通过外部回调。

这怎么可能最容易实现?

例子:

public class Example
{
ThreadedComponent _Cmp = new ThreadedComponent();


public Example()
{
_Cmp.ThreadedCallback += new ThreadedComponent.CB(Callback);

}

public void StartFunction()
{
// called in ThreadContextA
_Cmp.Start();

}

void Callback(Status s)
{
// is called in ThreadContextB
if(s == SomeStatus)
_Cmp.ContinueFunction(); // must be called in ThreadContextA

}
}

澄清

ContinueFunction 必须从与调用 StartFunction 相同的 ThreadContext 调用。这不一定是一个 UI 线程,但目前它当然是一个按钮处理程序。

最佳答案

没有“通用”方案,您的类不能对它在什么线程上使用以及什么对象可以提供您需要的 BeginInvoke() 方法做出很多假设。从以下选项之一中选择:

  • 不要提供任何帮助,只需记录可以在工作线程上引发该事件。无论 GUI 层中存在什么代码,当然总能在需要时弄清楚如何使用 BeginInvoke()。

  • 允许客户端代码通过您的类构造函数传递一个 Control 对象。您可以存储它并调用它的 BeginInvoke() 方法。这行得通,但不是很漂亮,因为您的类现在只能在 Winforms 项目中使用。

  • 公开类型为 ISynchronizeInvoke 的名为“SynchronizingObject”的属性。 GUI 层现在有选项 要求您调用 ISynchronizeInvoke.BeginInvoke()。如果属性已设置,您将执行的操作,否则直接触发事件。几个 .NET Framework 类执行此操作,如 Process、FileSystemWatcher、EventLog 等。但是它与以前的解决方案存在相同的问题,该接口(interface)在非 Winforms 应用程序中不容易使用。

  • 要求客户端代码在 UI 线程上创建您的对象。并在构造函数中复制 SynchronizationContext.Current。稍后,您可以使用它的 Post() 方法来调用。这是最兼容的选项,.NET 中的所有 GUI 类库都为此属性提供了一个值。

当你选择后面的项目符号之一时,请记住这个问题。客户端代码将获得与线程代码执行完全不同步的事件。具体的事件处理程序有点可能想要访问类的属性以了解有关类状态的更多信息。该状态不太可能仍然有效,因为您的线程已经顺利通过了 BeginInvoke() 调用。客户端代码根本没有选择插入锁来防止造成麻烦的选项。如果这是一个真正的问题,你应该强烈考虑帮助,通常是这样。

关于c# - 通用 BeginInvoke Scheme 以确保在同一线程上下文中调用函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24382735/

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