具有方法的接口包含 ValueTuple

4es*_*est 1 c# tuples interface task async-await

我有界面:

public Interface Inter1
{
 ....
 Task<(ITestBulk testBulk, bool resultBulk)> GetBulk(int par1, int par2, string par3);
}
Run Code Online (Sandbox Code Playgroud)

然后得到了一些方法:

 class MyClass{

   internal bool m_resultBulk;

 internal async void NewBulk()
 {
   ....
   (ITestBulk, m_resultBulk) = await service.GetBulk(1, 2, "ggg");
 } 
}
Run Code Online (Sandbox Code Playgroud)

m_resultBulk找不到。我做错了什么?

Dai*_*Dai 5

(作为旁注,您的NewBulk方法应该返回Task,否则其调用者无法等待其完成 - 避免启动“即发即忘”异步逻辑的代码很重要,因为在异步继续完成后不可能安全地清理(或正确捕获错误) - 唯一的例外是 WinForms 和 WPF 中的事件处理程序 - 这是因为它们的同步上下文将正确处理任何失败的延续。 - 此外,异步方法通常应具有以后缀 ) 结尾的名称...Async

无论如何,您的主要问题是您的调用站点GetBulk(应该命名为GetBulkAsync)没有正确声明ValueTuple返回本地。

你想要这个:

class MyClass
{
    private bool lastNewBulkResult;

    internal async Task NewBulkAsync()
    {
        (ITestBulk testBulk, bool resultBulk) = await this.service.GetBulkAsync( 1, 2, "ggg" ); // Specify `ConfigureAwait` as appropriate too.

        this.lastNewBulkResult = resultBulk;
    }
}
Run Code Online (Sandbox Code Playgroud)

然而这段代码有问题: after 的延续GetBulkAsync可能会在任何线程上运行 - 这意味着你的实例状态(即它的字段)正在以线程不安全的MyClass方式发生变化。解决方案是重新设计类以依赖不可变状态并通过方法参数和返回值(或异步结果)表示状态变化,从而完全避免线程安全问题。

关于混合ValueTupleawait

这个说法:

(ITestBulk testBulk, bool resultBulk) = await this.service.GetBulkAsync( 1, 2, "ggg" );
Run Code Online (Sandbox Code Playgroud)

相当于这样:

Task<(ITestBulk testBulk, bool resultBulk)> task = this.service.GetBulkAsync( 1, 2, "ggg" );
(ITestBulk testBulk, bool resultBulk) = await task;
Run Code Online (Sandbox Code Playgroud)

并且也相当于这样:

Task<(ITestBulk testBulk, bool resultBulk)> task = this.service.GetBulkAsync( 1, 2, "ggg" );
(ITestBulk testBulk, bool resultBulk) tupleValue = await task;
ITestBulk testBulk = tupleValue.testBulk;
bool resultBulk = tupleValue.resultBulk;
Run Code Online (Sandbox Code Playgroud)

或者这个(用于var声明端类型推断):

var task = this.service.GetBulkAsync( 1, 2, "ggg" );
var tupleValue = await task;
ITestBulk testBulk = tupleValue.testBulk;
bool resultBulk = tupleValue.resultBulk;
Run Code Online (Sandbox Code Playgroud)

或这个:

var tupleValue = await this.service.GetBulkAsync( 1, 2, "ggg" );
ITestBulk testBulk = tupleValue.testBulk;
bool resultBulk = tupleValue.resultBulk;
Run Code Online (Sandbox Code Playgroud)