gpt4 book ai didi

来自 C DLL 回调的 C# 跨线程 UI 操作

转载 作者:太空宇宙 更新时间:2023-11-04 08:21:28 24 4
gpt4 key购买 nike

我有 C 风格的 Dll,我必须在 C# 中使用它。我为图书馆创建了一个 Pinvoke 包装器。一切正常,但其中一个 C 函数接受函数指针(回调)。因此,在我的 C# 包装器中,它是一个 static 类,我添加了以下代码:

[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate void CallbackType(uint status);

/* To prevent garbage collection of delegate, need to keep a reference */
static CallbackType privCallback;

[DllImport(DLL_FILE_NAME, CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl)]
public static extern int SetCallback(uint handle, CallbackType callback);

public static int SetMyCallback(uint handle, CallbackType callback)
{
return SetCallback(handle, callback);
}

现在,在我的 C# Form 类中,

private void RefreshCallback(uint status)
{
this.statusLabel.Text = "Status Code: "+ status.toString();
}

private void myBtn_Click(object sender, EventArgs e)
{
int status, handle = 0;
...
status = MyDllWrapper.SetMyCallback(handle, RefreshCallback);
...
}

我的回调被调用的那一刻,我得到一个错误:

Cross-thread operation not valid

我希望回调函数在 UI 线程中运行。我应该在包装器中进行哪些更改才能实现此目的。

我想保持 Form 类简洁,包装类易于最终用户使用。因此,如果需要复杂的代码来处理这种情况,我想在包装器中进行处理,以便最终用户可以轻松使用我的 dll。

此外,我的静态包装器中委托(delegate)的静态实例是否会阻止它被垃圾回收。

最佳答案

您可以(大部分)检测回调是否转到 GUI 代码,并从与 UI 代码关联的线程自动执行。

public static int SetMyCallback(uint handle, CallbackType callback)
{
var callbackB = callback;
var syncTarget = callback.Target as System.Windows.Forms.Control;
if (syncTarget != null)
callbackB = (v) => syncTarget.Invoke(callback, new object[] { v });
return SetCallback(handle, callbackB);
}

另一种选择是根据用于调用 SetMyCallback 的线程创建一个 SynchronizationContext,然后使用该上下文进行调用。

关于来自 C DLL 回调的 C# 跨线程 UI 操作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33221157/

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