如何创建异步函数

How can i create an async function?

本文关键字:异步 函数 创建 何创建      更新时间:2023-10-16

我的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();
}

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

//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)
     {
     }
}

我应该怎么做才能在类中拥有真正的异步和非阻塞成员函数?我在这里错过了什么?

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

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

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

如果您使用的是.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本身异步调用,并且不会阻塞调用方线程。