在你的C#代碼,聲明你的本地C++方法與DllImport屬性,並從
BackgroundWorker.ProgressChanged
處理程序調用此方法。
免責聲明:我沒有測試過任何這些代碼,這可能不是最好的方法,但至少在理論上我認爲這會起作用。希望這裏更有經驗的成員之一可以驗證這是否確實是正確的。
這假設你從C#啓動後臺工作,並且你想在C#中使用ProgressChanged
事件(我認爲這是你的UI在C#中的情況)。
您仍然可以使用C#中的BackgroundWorker
,但只是把它叫使用我上面提到的的DllImport你的本地方法。您還可以修改方法的簽名,以獲取與ReportProgress
的簽名匹配的函數指針,然後從您的本機代碼調用該代理。
MSDN在Marshalling delegates and function pointers上有一些文章(儘管這些例子都使用C++/CLI)。您可能還想查看DLLImport和MarshalAs屬性以及UnmanagedType枚舉的文檔。
舉例來說,如果你的本地方法是
void foo(int arg1, BOOL arg2)
{
// Your code here
}
,你會在你的本機代碼定義一個函數指針類型爲
// Corresponds to void BackgroundWorker.ReportProgress(int progress, object state)
typedef void (*NativeReportProgress) (int, void*);
,改變你的本地簽名
void foo(int arg1, BOOL arg2, NativeReportProgress progressPtr)
{
// Some code.
progressPtr(progressValue, stateVar);
}
您的DLLImport
對於foo
看起來像
// Delegate type for BackgroundWorker.ReportProgress
delegate void ReportProgressDelegate(int progress, object state);
// The MarshalAs attribute should handle the conversion from the .NET
// delegate to a native C/C++ function pointer.
[DLLImport]
void foo([MarshalAs(UnmanagedType.I4)] Int32 arg1,
[MarshalAs(UnmanagedType.Bool)] bool arg2,
[MarshalAs(UnmanagedType.FunctionPointer)] ReportProgressDelegate progressDel);
然後你的工人看起來像
void DoWork(object sender, DoWorkEventArgs e)
{
var worker = (BackgroundWorker)sender;
// Notice that worker.ReportProgress is not followed the by().
// We're not actually calling the method here, we're just passing
// a function pointer to that method into foo.
foo(intArg, boolArg, worker.ReportProgress);
}
希望這取得了一定的意義(希望這是正確的,太!)
只是一個抽象的概念:鑑於BackgroundWorker的只是一個單獨的線程,可以在調用C#聲明不安全的代碼段;分開一個新的線程;並聲明一個函數指針來報告進度。總之,你有沒有在線索和代表的抽象層次之下進行編程? – 2012-08-10 21:58:07
寫它的本地代碼有什麼意義?您使用託管對象,因此您可以使用託管代碼編寫這些內容。如果你想用native C++寫這樣的東西,那麼你需要本地代碼 – 2012-08-11 00:01:14
@Even Dark首先你的評論並不涉及到問題。但不管怎麼說。在C#中編寫用戶界面更加方便,C++中的計算密集型代碼,我甚至不會說你沒有選擇的情況,因爲你沒有啓動項目,只需要一個代碼。而當你有C++和C#代碼時,你可能需要在它們之間進行一些溝通 - 在我的情況下,我需要報告進度。 – sergtk 2012-08-11 14:24:13