簡體   English   中英

來自C DLL回調的C#跨線程UI操作

[英]C# cross thread UI operation from C DLL callback

我有C風格的Dll,必須在C#中使用。 我為該庫創建了一個Pinvoke包裝器。 一切工作正常,但是C函數之一接受一個函數指針(回調)。 因此,在我的C#包裝器(這是一個靜態類)中,我添加了以下代碼:

[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。

另外,我的靜態包裝器中的委托的靜態實例是否會將其從垃圾回收中保留下來。

您可以(大部分)檢測回調是否將轉到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 ,然后使用該上下文進行調用。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM