如何使用C#BackgroundWorker在本机C+中报告进度+;密码? 在VisualStudio解决方案中,我在C语言中实现了UI,并在原生C++中实现了一些代码。
我习惯于执行长操作的进度报告 < >我如何使用<代码>后台工作程序>代码来报告我的本地C++代码的进度?< /p> P> >我如何将下面的C代码改写为本机C++,并调用C语言获得的C++代码? 如果无法直接重写下面的代码,最好了解其他等效解决方案。谢谢如何使用C#BackgroundWorker在本机C+中报告进度+;密码? 在VisualStudio解决方案中,我在C语言中实现了UI,并在原生C++中实现了一些代码。,c#,c++,visual-c++,interop,C#,C++,Visual C++,Interop,我习惯于执行长操作的进度报告 < >我如何使用后台工作程序>代码来报告我的本地C++代码的进度?< /p> P> >我如何将下面的C代码改写为本机C++,并调用C语言获得的C++代码? 如果无法直接重写下面的代码,最好了解其他等效解决方案。谢谢 class MyClass { public void Calculate(object sender, DoWorkEventArgs e) { BackgroundWorker worker = sender as
class MyClass
{
public void Calculate(object sender, DoWorkEventArgs e)
{
BackgroundWorker worker = sender as BackgroundWorker;
for (int i = 0; i < StepCount; i++)
{
if (worker.CancellationPending)
{
e.Cancel = true;
break;
}
// code which handles current iteration here
worker.ReportProgress((i + 1) * 100 / StepCount,
"Report progress message");
}
}
}
class-MyClass
{
公共无效计算(对象发送方,DoWorkEventArgs e)
{
BackgroundWorker worker=发件人作为BackgroundWorker;
对于(int i=0;i
在C代码中,用DLIMLIPT属性声明您的本机C++方法,并从您的代码>后台工作人员调用此方法。
免责声明:我没有测试过任何代码,这可能不是最好的方法,但至少在理论上我认为这是可行的。希望这里有一位更有经验的成员能够验证这一点是否正确
这假设您正在从C#启动后台工作程序,并且希望在C#中更改ProgressChanged
事件(我假设是这样的,因为您的UI在C#中)
您仍然可以在C#中使用BackgroundWorker
,但只需让它使用上面提到的dlliport调用您的本地方法即可。您还可以修改方法的签名,以获取与ReportProgress
的签名匹配的函数指针,然后从本机代码调用该委托
MSDN上有一些文章(尽管示例都使用C++/CLI)。您可能还想查看和属性以及枚举的文档
例如,如果您的本机方法是
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);
}
对于foo
,您的DLLImport
如下所示
// 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);
}
那么你的工人看起来像
// 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);
}
希望这是有意义的(也希望它是正确的!)下面是一个例子。
它在x86 C#和本机Visual C++上进行了测试:
CppLayer.h:
#ifdef CPPLAYER_EXPORTS
#define CPPLAYER_API __declspec(dllexport)
#else
#define CPPLAYER_API __declspec(dllimport)
#endif
extern "C" {
typedef void (__stdcall *ReportProgressCallback)(int, char *);
typedef bool (__stdcall *CancellationPendingCallback)();
struct CPPLAYER_API WorkProgressInteropNegotiator
{
ReportProgressCallback progressCallback;
CancellationPendingCallback cancellationPending;
bool cancel;
};
CPPLAYER_API void __stdcall CppLongFunction(WorkProgressInteropNegotiator& negotiator);
}
CppLayer.cpp:
#include "stdafx.h"
#include "CppLayer.h"
#include <iostream>
extern "C"
{
// This is an example of an exported function.
CPPLAYER_API void __stdcall CppLongFunction(WorkProgressInteropNegotiator& negotiator)
{
const int STEP_COUNT = 12;
char * messages[3] = {"ONE", "TWO", "THREE"};
for (int i = 0; i < STEP_COUNT; i++)
{
Sleep(100);
if (negotiator.cancellationPending()) {
negotiator.cancel = true;
break;
}
std::cout << "Calculate " << i << std::endl;
negotiator.progressCallback((i + 1) * 100 / STEP_COUNT, messages[i % 3]);
}
}
};
以下链接可能有用: