组合等待与 ContinueWith
Combination await with ContinueWith
我遇到了以下我正在尝试理解的异步代码(针对此示例进行了简化):
class Program
{
static async Task Main(string[] args)
{
var foo = new Foo();
try
{
var bar = new Bar();
await foo.ComputeNumber(bar.GetNumberAsync());
}
catch (Exception e)
{
Console.WriteLine($"Logged exception: {e}");
}
Console.WriteLine($"The number is {foo.Number}");
Console.ReadKey();
}
}
public class Foo
{
public int Number { get; private set; } = 0;
public async Task ComputeNumber(Task<int> inputTask)
{
await inputTask.ContinueWith(x => Number = x.Result);
}
}
public class Bar
{
public async Task<int> GetNumberAsync()
{
return await Task.Factory.StartNew(() =>
{
if (DateTime.Now.Date.DayOfWeek != DayOfWeek.Monday)
{
throw new Exception("This function works only on Mondays.");
}
return 17;
});
}
}
这段代码按我预期的方式工作(至少我希望如此),但我认为这个问题应该通过以下方式之一解决(我认为两者都是正确的)。 Bar
class 将保持不变。
第一种(async/await)方法:
class Program
{
static async Task Main(string[] args)
{
var foo = new Foo();
try
{
var bar = new Bar();
await foo.ComputeNumber(bar.GetNumberAsync());
}
catch (Exception e)
{
Console.WriteLine($"Logged exception: {e}");
}
Console.WriteLine($"The number is {foo.Number}");
Console.ReadKey();
}
}
public class Foo
{
public int Number { get; private set; } = 0;
public async Task ComputeNumber(Task<int> inputTask)
{
Number = await inputTask;
}
}
第二种(基于任务的)方法:
class Program
{
static void Main(string[] args)
{
var foo = new Foo();
var bar = new Bar();
foo.ComputeNumber(bar.GetNumberAsync());
Console.WriteLine($"The number is {foo.Number}");
Console.ReadKey();
}
}
public class Foo
{
public int Number { get; private set; } = 0;
public void ComputeNumber(Task<int> inputTask)
{
inputTask.ContinueWith(x =>
{
if (x.IsFaulted)
{
Console.WriteLine($"Logged exception: {x.Exception}");
}
else
{
Number = x.Result;
}
});
}
}
对于为什么可以这样编写使用异步代码的原始示例的每一种解释,我都很感激。
您可以将 await
视为替代 ContinueWith
大部分用法的语言功能,因此将两者混合似乎没有必要。
请注意,您的第二次重写与第一次重写在两个方面不同。
它吞下了错误而不是暴露它们。
它没有 return 和 Task
所以调用者不知道什么时候 Number
被设置为最终结果。
ComputeNumber
的目的不明(这可能是因为为了在此处发布而对其进行了简化)。为什么不简单地 await bar.GetNumberAsync()
然后在后续语句中使用获得的值? await
的要点是允许 Task<T>
在程序代码中被视为与 T
相同。
我遇到了以下我正在尝试理解的异步代码(针对此示例进行了简化):
class Program
{
static async Task Main(string[] args)
{
var foo = new Foo();
try
{
var bar = new Bar();
await foo.ComputeNumber(bar.GetNumberAsync());
}
catch (Exception e)
{
Console.WriteLine($"Logged exception: {e}");
}
Console.WriteLine($"The number is {foo.Number}");
Console.ReadKey();
}
}
public class Foo
{
public int Number { get; private set; } = 0;
public async Task ComputeNumber(Task<int> inputTask)
{
await inputTask.ContinueWith(x => Number = x.Result);
}
}
public class Bar
{
public async Task<int> GetNumberAsync()
{
return await Task.Factory.StartNew(() =>
{
if (DateTime.Now.Date.DayOfWeek != DayOfWeek.Monday)
{
throw new Exception("This function works only on Mondays.");
}
return 17;
});
}
}
这段代码按我预期的方式工作(至少我希望如此),但我认为这个问题应该通过以下方式之一解决(我认为两者都是正确的)。 Bar
class 将保持不变。
第一种(async/await)方法:
class Program
{
static async Task Main(string[] args)
{
var foo = new Foo();
try
{
var bar = new Bar();
await foo.ComputeNumber(bar.GetNumberAsync());
}
catch (Exception e)
{
Console.WriteLine($"Logged exception: {e}");
}
Console.WriteLine($"The number is {foo.Number}");
Console.ReadKey();
}
}
public class Foo
{
public int Number { get; private set; } = 0;
public async Task ComputeNumber(Task<int> inputTask)
{
Number = await inputTask;
}
}
第二种(基于任务的)方法:
class Program
{
static void Main(string[] args)
{
var foo = new Foo();
var bar = new Bar();
foo.ComputeNumber(bar.GetNumberAsync());
Console.WriteLine($"The number is {foo.Number}");
Console.ReadKey();
}
}
public class Foo
{
public int Number { get; private set; } = 0;
public void ComputeNumber(Task<int> inputTask)
{
inputTask.ContinueWith(x =>
{
if (x.IsFaulted)
{
Console.WriteLine($"Logged exception: {x.Exception}");
}
else
{
Number = x.Result;
}
});
}
}
对于为什么可以这样编写使用异步代码的原始示例的每一种解释,我都很感激。
您可以将 await
视为替代 ContinueWith
大部分用法的语言功能,因此将两者混合似乎没有必要。
请注意,您的第二次重写与第一次重写在两个方面不同。
它吞下了错误而不是暴露它们。
它没有 return 和
Task
所以调用者不知道什么时候Number
被设置为最终结果。
ComputeNumber
的目的不明(这可能是因为为了在此处发布而对其进行了简化)。为什么不简单地 await bar.GetNumberAsync()
然后在后续语句中使用获得的值? await
的要点是允许 Task<T>
在程序代码中被视为与 T
相同。