【问题标题】:Framework like thread marshalling像线程编组这样的框架
【发布时间】:2011-12-19 08:40:43
【问题描述】:

我一直认为我可以使用 SynchronizationContext 来编组对另一个线程的调用。显然我错了,因为 SyncCtx.Send() 除了调用给定的委托(保持在同一个线程上)之外什么都不做。我真的需要从 SynchronizationContext 派生并在线程上下文上工作吗?我觉得错过了什么。

我想要实现的目标:想象一个用于在应用程序中执行命令的小 API。您还可以在后台线程上执行命令,因为您可以分配一个委托以在命令完成执行时运行。这个“Call-me-when-done”-Delegate 获得一个包含成功/失败标志、可选异常信息等的单个参数(状态)。我想在原始调用线程上调用这个委托,这样使用 lib 的开发人员就不会需要处理所需的调用等。我只想把它拿走,让他们做简单的非线程感知编程。如果您不给它一些控制作为目标,WindowsFormsSynchronizationContext 似乎也无济于事。

感谢您的帮助!

【问题讨论】:

    标签: c# winforms multithreading synchronizationcontext


    【解决方案1】:

    当您在 winforms 中并使用同步上下文时,调用将被编组到 GUI 线程。

    对于您的具体情况,我想这样的事情应该可以工作,也许创建一个代表Command的类是个好主意

    public class CommandManager
    {
        private readonly SynchronizationContex _synchronizationContex;
    
        public CommandManager(SynchronizationContext synchronizationContex)
        {
            _synchronizationContex = synchronizationContex;
        }
    
        public void ExecuteAsync(Func<State> action, Action<State> callback)
        {
            ThreadPool.QueueUserWorkItem(o => {
                                                 state = action();
                                                 _synchronizationContex.Send(oo => callback(state));
                                              });
        } 
    }
    

    你会这样创建(在 GUI 线程中,例如在你的主窗体中)

    var commandManager = new CommandManager(SynchronizationContext.Current);
    

    你会这样使用它:

    commandManager.ExecuteAsync(() => new State() { Success = true }, 
                                 c => MessageBox.Show("success in the GUI thread"));
    

    【讨论】:

    • 您好,感谢您的回答,但实际上您犯了与我相同的错误。 SynchronizationContext 不做任何事情。 Send 只是在调用 Send 的同一线程上调用委托 -> 没有编组(使用反射器)。 WindowsFormsSynchronizationContext f.e.进行编组,但仅在给定的目标控件上。所以这也无济于事。
    • @Gope SynchronizationContext 只是WindowsFormsSynchronizationContext 的基类,当您在winforms 应用程序中时,SynchronizationContext.Current 拥有WindowsFormsSynchronizationContext,因此将编组您的线程。你是怎么得出它不编组的结论的?
    • 这很有趣!我正在研究这两个类的代码。我的整个代码都在 UnitTests 中运行,因此我必须自己构建 SyncCtx 并检查 ManagedThreadIds。从代码和生成的线程 ID 可以看出,基类没有编组。我没有想到框架将 WFSyncCtx 的实例放在 SC.Current 中......我将对此进行探讨,但您所说的非常有道理。我的测试课程对我隐藏了一些东西。 :D 谢谢!
    猜你喜欢
    • 2011-06-03
    • 2015-11-12
    • 1970-01-01
    • 2011-02-04
    • 2011-01-15
    • 2011-07-27
    • 2016-05-20
    • 1970-01-01
    • 2011-02-02
    相关资源
    最近更新 更多