我有接口:
public Interface Inter1
{
....
Task<(ITestBulk testBulk, bool resultBulk)> GetBulk(int par1, int par2, string par3);
}
然后得到了一些方法:
class MyClass{
internal bool m_resultBulk;
internal async void NewBulk()
{
....
(ITestBulk, m_resultBulk) = await service.GetBulk(1, 2, "ggg");
}
}
但是找不到m_resultBulk
。我做错了什么?
(作为旁注,您的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;
}
}
但是,此代码存在问题:GetBulkAsync
之后的延续可能会在任何线程上运行 - 这意味着MyClass
的实例状态(即其字段)正在以线程不安全的方式发生突变。解决方案是重新设计您的类以依赖于不可变状态,并通过方法参数和返回值(或异步结果)表示状态的变化,从而完全避免线程安全问题。
关于混合ValueTuple
和await
:
此声明:
(ITestBulk testBulk, bool resultBulk) = await this.service.GetBulkAsync( 1, 2, "ggg" );
相当于这个:
Task<(ITestBulk testBulk, bool resultBulk)> task = this.service.GetBulkAsync( 1, 2, "ggg" );
(ITestBulk testBulk, bool resultBulk) = await task;
也相当于这个:
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;
或者这个(使用var
进行声明端类型推断):
var task = this.service.GetBulkAsync( 1, 2, "ggg" );
var tupleValue = await task;
ITestBulk testBulk = tupleValue.testBulk;
bool resultBulk = tupleValue.resultBulk;
或者这个:
var tupleValue = await this.service.GetBulkAsync( 1, 2, "ggg" );
ITestBulk testBulk = tupleValue.testBulk;
bool resultBulk = tupleValue.resultBulk;
在行中
(ITestBulk, m_resultBulk) = await service.GetBulk(1, 2, "ggg");
左侧的元组缺少第一个元组元素的变量名称。 如果您不需要ITestBulk
值,则可以使用如下丢弃:
(_, m_resultBulk) = await service.GetBulk(1, 2, "ggg");
如果需要,需要声明一个变量(因为不能在元组中混合声明和解构):
ITestBulk testBulk;
(testBulk, m_resultBulk) = await service.GetBulk(1, 2, "ggg");