2

我的 C++ 类中有几个成员函数,我将它们打包为 dll 并尝试在 C# 应用程序中使用它们。
我试图通过简单地使用线程执行它们然后将它们分离()来创建两个异步函数,这样它们就不会阻塞调用者线程直到它们结束。在基于 C++ 的应用程序中,每当我使用线程以这种方式调用函数时,它们都可以工作,但是当我尝试从 c# 调用我的异步函数之一时,我的应用程序崩溃或挂起!
这些是我所谓的异步函数!:

void xGramManipulator::CreateMonoGramAsync()
{
    thread t(&xGramManipulator::ReadMonoGram, this);
    t.detach();
}

void xGramManipulator::CreateBiGramAsync()
{
    thread t = thread(&xGramManipulator::ReadBiGram, this);
    t.detach();
}

这是驻留在 dll 中的 c 中的包装函数:

//header
CDLL_API void CreateMonoGramAsync(void);
//cpp
CDLL_API void CreateMonoGramAsync(void)
{
    xG.CreateMonoGramAsync();
}

这是调用该函数的 c# 应用程序:

 private void btnTest_Click(object sender, EventArgs e)
 {
     try
     {
        CreateBiGramAsync();
        CreateMonoGramAsync();
     }
     catch (Exception)
     {
     }

}

我应该怎么做才能在我的班级中拥有真正的异步和非阻塞成员函数?我在这里想念什么?

4

2 回答 2

2

我的猜测是,在将它们导入 C# 时,您没有指定调用约定——默认情况下,C# 将使用 C#,stdcall而 C++ 将导出为cdecl. 你必须:

[DllImport("CDll.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern void CreateMonoGramAsync();

或者,您当然可以returntype __stdcall在 C++ 中声明您的方法时指定。我还假设您已经正确声明了该函数(使用extern "C" __declspec(dllexport)等)

于 2013-07-29T23:17:34.573 回答
1

如果您使用的是 .NET 4.5,则可以使用Task类来实现异步方法调用。

考虑以下示例:

    static void Foo()
    {
        Thread.Sleep(2000);
        Console.WriteLine("Foo called asynchronously!");
    }

    static void Main(string[] args)
    {
        var bar = Task.Factory.StartNew(() => { Foo(); });

        Console.WriteLine("Called synchronously!");

        Console.ReadLine();
    }

Foo()每当执行此代码时,都会启动一个异步调用,等待两秒钟,然后写入Foo called asynchronously!控制台。另一个Console.WriteLine调用是同步的,并且在异步调用开始后立即运行。

输出将是:

Called synchronously!
Foo called asynchronously!

由于调用者的线程没有被调用阻塞Foo()

你可以对你的代码做同样的事情,你甚至可以删除你当前在你的方法中拥有的线程以使它们异步。原因是即使他们创建了自己的线程,.NET 运行时仍将等待这些函数返回。你最好这样称呼他们:

Task.Factory.StartNew(CreateBiGramAsync());

这样,它们实际上会从 .NET 本身异步调用,并且不会阻塞调用者线程。

于 2013-07-29T23:10:01.810 回答