如何在 C# 中的 ContinueWith 之前使用 Delay Task.ContineWith?
How to do Task.ContineWith using a Delay before the ContinueWith in C#?
我知道我可以像这样执行一个简单的延迟任务:
Task.Delay(iDelayInMilliseconds).ContinueWith(() => SomeMethod());
我可以像这样将两种不同的方法链接为顺序任务:
Task.Run(() => SomeMethod()).ContinueWith(() => AnotherMethod());
我想不通的是这样的:
Task.Run(() => SomeMethod()).Delay(iDelayInMilliseconds).ContinueWith(() => AnotherMethod());
实际上,我希望 SomeMethod() 到 运行,然后是延迟,然后是 AnotherMethod()。
谁能帮我解决这个问题?
Task.Run(async () =>
{
SomeMethod();
await Task.Delay(iDelayInMilliseconds);
}).ContinueWith(cw => AnotherMethod());
这里,我们实际上需要等待内部Task
(即Task.Delay(iDelayInMilliseconds)
)完成,否则Task
[= Task.Run()
编辑的 33=] 将 return 立即将其 Status
设置为 RanToCompletion
。
当然,如果这不需要在ThreadPool
线程上运行,你可以一并删除Task.Run()
:
// ...
SomeMethod();
await Task.Delay(iDelayInMilliseconds);
AnotherMethod();
..这意味着您必须将父方法标记为 async
并使用 return Task<T>
而不是 T
或 Task
如果它 returns void
.
我建议为此查看 Microsoft 的 Reactive Framework。它比任务更强大,恕我直言,可以像 LINQ 查询一样使用,并且很容易与任务和异步操作互操作。
在您的情况下,您的代码可以如下所示:
void Main()
{
var iDelayInMilliseconds = 4000;
IObservable<int> query =
from x in Observable.Start(() => SomeMethod())
from y in Observable.Timer(TimeSpan.FromMilliseconds(iDelayInMilliseconds))
from z in Observable.Start(() => AnotherMethod())
select x + z;
IDisposable subscription = query.Subscribe(w => Console.WriteLine(w));
}
public int SomeMethod() => 1;
public int AnotherMethod() => 2;
这需要 4,000
毫秒并在控制台上生成 3
。
如果您想提前停止查询,只需在 subscription
上调用 .Dispose()
。
如果您的一些方法是 async
并且您想要返回 Task<int>
那么您可以这样做:
void Main()
{
var iDelayInMilliseconds = 4000;
IObservable<int> query =
from x in Observable.StartAsync(() => SomeMethod())
from y in Observable.Timer(TimeSpan.FromMilliseconds(iDelayInMilliseconds))
from z in Observable.Start(() => AnotherMethod())
select x + z;
Task<int> task = query.ToTask();
Console.WriteLine(task.Result);
}
public async Task<int> SomeMethod() => await Task.Run(() => 1);
public int AnotherMethod() => 2;
这仍然会以正确的延迟产生正确的结果。
只需 NuGet "System.Reactive" 并将 using System.Reactive.Linq;
添加到您的代码中以使其正常工作。
我知道我可以像这样执行一个简单的延迟任务:
Task.Delay(iDelayInMilliseconds).ContinueWith(() => SomeMethod());
我可以像这样将两种不同的方法链接为顺序任务:
Task.Run(() => SomeMethod()).ContinueWith(() => AnotherMethod());
我想不通的是这样的:
Task.Run(() => SomeMethod()).Delay(iDelayInMilliseconds).ContinueWith(() => AnotherMethod());
实际上,我希望 SomeMethod() 到 运行,然后是延迟,然后是 AnotherMethod()。
谁能帮我解决这个问题?
Task.Run(async () =>
{
SomeMethod();
await Task.Delay(iDelayInMilliseconds);
}).ContinueWith(cw => AnotherMethod());
这里,我们实际上需要等待内部Task
(即Task.Delay(iDelayInMilliseconds)
)完成,否则Task
[= Task.Run()
编辑的 33=] 将 return 立即将其 Status
设置为 RanToCompletion
。
当然,如果这不需要在ThreadPool
线程上运行,你可以一并删除Task.Run()
:
// ...
SomeMethod();
await Task.Delay(iDelayInMilliseconds);
AnotherMethod();
..这意味着您必须将父方法标记为 async
并使用 return Task<T>
而不是 T
或 Task
如果它 returns void
.
我建议为此查看 Microsoft 的 Reactive Framework。它比任务更强大,恕我直言,可以像 LINQ 查询一样使用,并且很容易与任务和异步操作互操作。
在您的情况下,您的代码可以如下所示:
void Main()
{
var iDelayInMilliseconds = 4000;
IObservable<int> query =
from x in Observable.Start(() => SomeMethod())
from y in Observable.Timer(TimeSpan.FromMilliseconds(iDelayInMilliseconds))
from z in Observable.Start(() => AnotherMethod())
select x + z;
IDisposable subscription = query.Subscribe(w => Console.WriteLine(w));
}
public int SomeMethod() => 1;
public int AnotherMethod() => 2;
这需要 4,000
毫秒并在控制台上生成 3
。
如果您想提前停止查询,只需在 subscription
上调用 .Dispose()
。
如果您的一些方法是 async
并且您想要返回 Task<int>
那么您可以这样做:
void Main()
{
var iDelayInMilliseconds = 4000;
IObservable<int> query =
from x in Observable.StartAsync(() => SomeMethod())
from y in Observable.Timer(TimeSpan.FromMilliseconds(iDelayInMilliseconds))
from z in Observable.Start(() => AnotherMethod())
select x + z;
Task<int> task = query.ToTask();
Console.WriteLine(task.Result);
}
public async Task<int> SomeMethod() => await Task.Run(() => 1);
public int AnotherMethod() => 2;
这仍然会以正确的延迟产生正确的结果。
只需 NuGet "System.Reactive" 并将 using System.Reactive.Linq;
添加到您的代码中以使其正常工作。