c# - 我们如何在 C++/CX 中等待 C# 异步委托(delegate)函数

标签 c# windows asynchronous c++-cx

这是关于C++(不同平台的共享代码)与C#(Windows Universal App)之间的通信。我们知道下面是从C++C#的函数调用。

C#

class FooCS
{
    FooCS()
    {
        FooC c = new ref FooC(); 
        c.m_GetSomeValueEvent = GetSomeValueEvent;
        // Some other stuff ...
    }

    string GetSomeValueEvent()
    {
        // Some other stuff ... 
        return "Hello World"; 
    }
}

C++

public delegate Platform::String GetSomeValueEventHandler(); 

class FooC
{
    public:
    event GetSomeValueEventHandler^ m_GetSomeValueEvent; 
    void someFunction(){
        Platform::String^ str = m_GetSomeValueEvent();
        // Some other stuff ... 
    }
}

上面的内容非常简单。但问题是 C# 中的这个字符串 GetSomeValueEvent() 执行一些繁重的任务,例如从数据库读取数据,我必须使其 async

    async Task<string> GetSomeValueEvent() {
        // Some other stuff ... 
        return "Hello World"; 
    }

现在问题来了:如何让我的C++代码等待这个委托(delegate)函数的返回?也就是说,下面的签名应该修改成什么?

    public delegate Platform::String GetSomeValueEventHandler(); 

我一直在谷歌上搜索,找不到解决这个问题的正确术语。如果您确定这是不可能的,至少很高兴知道。


最终,这就是我们所做的:

    string GetSomeValueEvent() {
        // Convert a async method to non-async one
        var val = someAsyncMethod().Result; 
        // Some other stuff ... 
        return "Hello World"; 
    }

您必须确保 GetSomeValueEvent 没有在主线程上运行以防止死锁。

最佳答案

UPD:从事件中返回一个值是一个非常糟糕的主意。考虑其他选项,例如某种可观察模式,但只有一个观察者。

正如@RaymondChen 所提到的,对于异步事件,最好使用延迟模式。这是 Windows 运行时中常用的模式。

添加 GetDeferral()方法到您的事件参数,它返回一个特殊的延迟对象。此对象必须具有 Complete()通知您的代码异步操作已完成的方法。

============================================= ============================

async关键字实际上不会改变函数原型(prototype)。因此,您只需更改委托(delegate)中的返回值以匹配原始值 (Task<string>)。

但有一个问题:Windows 运行时没有 Task<>类型,它是 TPL 的一部分,它是一个 .NET 库。相反,Windows 运行时使用 IAsyncOperation<>IAsyncAction表示异步操作。

所以这是你需要做的:

  1. 更改代表的签名:

    public delegate Windows::Foundation::IAsyncOperation<Platform::String> GetSomeValueEventHandler();
    
  2. 使用 AsAsyncOperation()转换的扩展方法 Task<>IAsyncOperation<> :

    async Task<string> GetSomeValueEvent()
    {
        // Some other stuff ... 
        return "Hello World"; 
    }
    
    IAsyncOperation<string> GetSomeValueEventWrapper()
    {
        return GetSomeValueEvent().AsAsyncOperation();
    }
    
    FooCS()
    {
        FooC c = new ref FooC(); 
        c.m_GetSomeValueEvent = GetSomeValueEventWrapper;
        // Some other stuff ...
    }
    

关于c# - 我们如何在 C++/CX 中等待 C# 异步委托(delegate)函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32488862/

相关文章:

c# - 如何从抽象类创建对象?

C++ Windows/Linux 线程同步事件

c# - 修改 IEnumerable 类型

c# - 一对一关系导致异常 : AssociationSet is in the 'Deleted' state. 给定多重约束

.net - 运行 Windows 应用程序的 Docker

ios - 异步代码不会执行,直到应用程序在应用程序 :didReceiveRemoteNotification:fetchCompletionHandler: 中处于前台

java - 等待异步任务完成

typescript 异步/等待无法确定正确的返回类型

c# - UWP 应用构建失败 "Microsoft.UI.Xaml.Markup could not be found"

windows - 在不映射到驱动器的情况下使用 TCL 访问 XP 中的共享文件夹