是否可以在线程中对非托管函数执行C#回调?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了是否可以在线程中对非托管函数执行C#回调?相关的知识,希望对你有一定的参考价值。

这是关于this的后续问题。基本上,我试图使用C++包装器将C#回调发送到Python模块。问题是,由于main方法是阻塞方法(while循环一直将信息分派给回调。问题是,它是如此之快,C# GUI无法对其进行处理,因此变得无响应。我尝试使用计时器Tick()事件来每秒显示一次信息,但是似乎回调使进程耗费了太多时间,因此计时器本身无法输出。我什至尝试使用线程来执行回调,但是同样失败,这意味着应用程序仍然没有响应。我的问题是,我可以做些什么来从C#方面纠正此问题吗?例如,我们可以使回调以某种方式在不导致应用程序无响应的单独线程中运行吗?

更新:这里是一些更多信息(来自链接的问题):

我的DllImport如下:

[DllImport(@"Core_DLL.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern int Initialize(bool showFeed);

[DllImport(@"Core_DLL.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern void Start(bool async);

[DllImport(@"Core_DLL.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern void Stop();

[DllImport(@"Core_DLL.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern void SetCpuAffinity(int mask);



public delegate void CallbackDelegate(bool status, string message);
[MethodImplAttribute(MethodImplOptions.InternalCall)]

[DllImport(@"Core_DLL.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern void AddCallback(IntPtr fn);

[DllImport(@"Core_DLL.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern void RemoveCallback(IntPtr fn);

这是我的C#回调:

private CallbackDelegate del;
public void SetUpCallback()
{
    txtLog.Text += "Registering C# callback...
";
    del = new CallbackDelegate(callback01);
    AddCallback(Marshal.GetFunctionPointerForDelegate(del));
    txtLog.Text += "Calling passed C++ callback...
";
}

bool status;
string id;
public void callback01(bool status, string id)
{
     this.status = status;
     this.id = id;
}

基本上,当您调用Start()时,主循环开始,并且回调被间接调用。

如果我尝试使用线程运行Start,则不再获得任何回调输出:


Thread t;
private void btnRunService_Click(object sender, EventArgs e)
{
    tmrFetchStatus.Start();
    //Start(chkboxAsync.Checked);
    t = new Thread(new ThreadStart(() =>
    {
         RunService();
    }));
    t.IsBackground = true;
    t.Start();
}

void RunService()
{
    Start(chkboxAsync.Checked);

    if (txtLog.InvokeRequired)
    {
        txtLog.Invoke(new MethodInvoker(()=>
        {
            txtLog.Text += "OK";  
        }));
    }
    else
    {
        txtLog.Text += "OK"; 
    }
}

答案

正如所评论的,导致线程问题是因为没有在与Start方法相同的线程上调用AddCallback方法。

当使用依赖互操作调用(或通常实际上是依赖调用)时,最好保持在同一线程上,除非您知道这无关紧要。

以上是关于是否可以在线程中对非托管函数执行C#回调?的主要内容,如果未能解决你的问题,请参考以下文章

满足条件时是不是可以在 GLSL 着色器中回调 C/C++ 函数/代码? [关闭]

C++/CLI:返回对非托管对象的引用

在c ++中对非数组变量使用delete [] [重复]

如何在android的jni线程中实现回调

iOS中-Block使用

在类内部处理回调时必须调用对非静态成员函数的引用