我试图使用下面的函数不返回true / false,除非Boolean Function arg返回true或超时到期。在当前状态下,如果布尔函数arg返回false,则立即返回false而不是循环并重试X更多毫秒。
public delegate bool BooleanFunction ();
public static async Task<bool> Wait(uint Milliseconds, BooleanFunction Function)
{
var StartTime = Environment.TickCount;
do
{
if (Function())
{
return true;
}
Thread.Yield();
}
while (Environment.TickCount < StartTime + Milliseconds);
return false;
}
答案 0 :(得分:3)
您需要使用await Task.Yield
代替Thread.Yield
if (Function())
{
return true;
}
await Task.Yield();
如果您还想处理将异步委托传递给Wait
,请保留现有版本并添加以下重载:
public static async Task<bool> Wait(uint Milliseconds, Func<Task<bool>> Function)
{
var StartTime = Environment.TickCount;
do
{
if (await Function())
{
return true;
}
Thread.Yield();
}
while (Environment.TickCount < StartTime + Milliseconds);
return false;
}
然后你可以这样做:
var result = await Wait(10000, async () => await Test());
答案 1 :(得分:1)
Microsoft提出了另一种实现方法,即使用cancellationTokenSource和cancellationToken。
Microsoft about Task Cancellation
StackOverflow也有一些关于此的主题:
CancellationToken and CancellationTokenSource-How to use it?
转换为您的问题,调用者不会传递委托函数,而是传递System.Threading.CancellationToken对象。 Wait函数不是调用委托,而是定期检查CancellationToken对象是否请求取消。
这种方法与你的方法非常相似,只是它是一种更标准的模式。真正的好处是,您可以使用取消在一次通话中使用来自同一来源的令牌的所有任务。此外,它还具有内置超时功能。
另一个优点是取消的原因是在你的函数之外决定,它可以是超时,或者因为BooleanFunction返回true,甚至可能因为你的程序停止等等。即使在将来的版本中,停止等待的新理由是介绍,你的等待功能不必改变。它只是做它的工作,并定期检查CancellationIsRequested。
示例代码:
你的等待功能不会做很多事情,而是等待。我想你简化了这个,因为如果真的需要它,我猜你曾经使用过System.Timer。我们假设你必须做点什么
我有一个带有两个按钮的表单:buttonStartWait和buttonCancelWait。按下时,buttonStartWait将启动Wait,而buttonCancelWait将取消等待。
如果我们使用了你的方法,buttonCancelWait会使委托返回true。
代码如下(我也将Ticks的用法改为TimeSpan以便于阅读)
private CancellationTokenSource tokenSource = null;
private async void OnButtonStartWait_clicked(object sender, ...)
{
this.buttonStartWait.Enabled = false;
TimeSpan waitTime = GetWaitTime();
this.tokenSource = new tokenSource(waitTime);
// this makes sure that after waitTime cancellation is requested
await this.Wait(this.TokenSource.Token);
this.buttonstartWait.Enabled = true;
}
private async Task<bool> Wait(CancellationToken token)
{
while (!token.IsCancellationRequested)
{ // do the thing your function is supposed to do.
DoSomethingShort();
// if this function takes some time, pass the token to it
// and let it regularly check if cancellation is requested
DoSomethingLonger(token);
// or consider starting a Task which regularly checks
// if cancellation is requested
await Task.Run( () => DoSomethingLonger(token), token);
}
return token.IsCancellationRequested;
}
// a Wait function that really doesn't do anything but wait
// until cancellation is requested.
private async Task<bool> Wait(CancellationToken token)
{
while (!token.IsCancellationRequested)
{ // wait a short while
await Task.Wait(TimeSpan.FromSeconds(0.1), token;
}
return token.IsCancellationRequested;
}
private async void OnButtonCancelWait_clicked(object sender, ...)
{
if (this.TokenSource != null)
{
this.TokenSource.Cancel();
}
}