C#:如何通过以某种方式从另一个线程发出信号来强制从主线程“调用”一个方法

时间:2011-01-05 00:46:36

标签: c# winforms multithreading callback signals

对不起,对于长标题,我甚至不知道如何表达问题的方式

我正在使用一个库,它从主线程的不同上下文运行回调(是一个C库),我在C#中创建了回调,当我被调用时,我想只提出一个事件。

但是因为我不知道事件内部会是什么,所以我想找到一种方法来调用方法而不会出现锁等问题(否则第三方用户将不得不在事件中处理这个问题) ,非常难看)

有没有办法做到这一点? 我可以完全走错路,但我正在考虑winforms处理不同线程的方式(.Invoke事物)

否则我可以向窗口的消息循环发送消息,但我不太了解消息传递,如果我可以发送这样的“自定义”消息

示例:

private uint lgLcdOnConfigureCB(int connection, System.IntPtr pContext)
{
    OnConfigure(EventArgs.Empty);
    return 0U;
}

这个回调是从另一个我无法控制的程序调用的,我想在主线程中运行OnConfigure方法(处理我的winform的那个),怎么做呢? 或者换句话说,我想运行OnConfigure而不需要考虑锁

修改1:

我遇到此异常的问题:

CallbackOnCollectedDelegate已重试 消息:在GarbageCollector中收集的委托'G19dotNet!G19dotNet.LgLcd + lgLcdOnSoftButtonsCB :: Invoke'上运行回调。在非托管代码期间,应确保代理永远不会被删除,直到您确定它们永远不会被调用

编辑2:

我自己解决了问题,感谢Stackoverflow总能帮助我! 供将来参考:Defining a delegate as a function pointer

3 个答案:

答案 0 :(得分:6)

如果你正在使用WinForms而你想在UI线程上执行某些操作,则需要在某个控件上调用InvokeBeginInvoke(无论是Button还是在该线程上创建的Form或其他)。为了做到这一点,你需要引用它。

例如,使用您的代码并假设您有一个名为form的表单的引用:

private uint lgLcdOnConfigureCB(int connection, System.IntPtr pContext)
{
    form.Invoke(new MethodInvoker(() => OnConfigure(EventArgs.Empty)));
    return 0U;
}

答案 1 :(得分:3)

在调用第三方函数之前,请获取对Dispatcher.CurrentDispatcher的引用。在回调函数中,使用dispatcher.Invoke。

你最终得到的结果将是这样的:

class MyClass
{
    private Dispatcher dispatcher;
    public void runThirdParty()
    {
        this.dispatcher = Dispatcher.CurrentDispatcher;
        callThirdPartyFunction(myCallBack);
    }

    public void myCallBack()
    {
        this.dispatcher.Invoke(new Action(() =>
        {
            //code to run here.
        }));
    }
 }

答案 2 :(得分:3)

这种模式称为Event-based Asynchronous Pattern。链接的文章是关于如何使用它的一个很好的概述。 AsyncOperation类是此模式的关键。

此模式可能与您尝试解决的问题不完全吻合,但它可能会为您提供一些问题的见解。