我想要一個代碼塊,它應該在最大時間限制內執行。如果功能掛起,則應中止。從這個問題我改編了以下解決方案:
public static void ExecuteWithTimeLimit(int timeLimit_milliseconds, Func<bool> codeBlock)
{
Task task = Task.Factory.StartNew(() =>
{
codeBlock();
});
task.Wait(timeLimit_milliseconds);
}
這按我希望的方式作業:如果代碼codeBlock掛起并花費很長時間,則任務將中止。
但是,我希望Task有一個回傳值,以便我可以使用task.Result. 如果我將其實作到代碼中,它將不再起作用。事實上,任務并沒有被取消,GUI 完全凍結。
public static void ExecuteWithTimeLimit(int timeLimit_milliseconds, Func<bool> codeBlock)
{
Task<bool> task = Task<bool>.Factory.StartNew(() =>
{
return codeBlock();
});
task.Wait(timeLimit_milliseconds);
}
執行具有最大時間限制的回傳值的方法的正確方法是什么?
uj5u.com熱心網友回復:
我建議創建一個任務方法并使用等待。這將釋放執行緒,因此應用程式不會鎖定,一旦結果可用,它將跳回該執行緒這里是一個示例:
public async Task MyMethodAsync()
{
Task<string> longRunningTask = LongRunningOperationAsync();
// independent work which doesn't need the result of LongRunningOperationAsync can be done here
//and now we call await on the task
string result = await longRunningTask;
//use the result
Console.WriteLine(result);
}
public async Task<string> LongRunningOperationAsync() // assume we return an int from this long running operation
{
//Perform your task in here
await Task.Delay(5000); // 5 second delay to show how it releases thread
return "Task Complete";
}
uj5u.com熱心網友回復:
有很多關于帶有任務的取消令牌的問題。我建議讓您的生活更輕松并使用 Microsoft 的 Reactive Framework(又名 Rx)-NuGetSystem.Reactive并添加using System.Reactive.Linq;-然后您可以這樣做:
public static async Task<bool> ExecuteWithTimeLimit(TimeSpan timeLimit, Func<bool> codeBlock)
=> await Observable.Amb(
Observable.Timer(timeLimit).Select(_ => false),
Observable.Start(() => codeBlock()));
Observable.Amb接受 2 個或更多 observables 并且只從第一個觸發的 observable 回傳值。Observable.Timer在TimeSpan提供之后觸發單個值。Observable.Start執行任何代碼并回傳作為該代碼結果的單個值。
實際上Amb是計時器和代碼之間的競賽。
現在我可以像這樣運行它:
Task<bool> task =
ExecuteWithTimeLimit(TimeSpan.FromSeconds(1.0), () =>
{
Console.WriteLine("!");
Thread.Sleep(TimeSpan.FromSeconds(2.0));
Console.WriteLine("!!");
return true;
});
task.Wait();
Console.WriteLine(task.Result);
當我運行時,我在控制臺上得到了這個:
!
False
!!
如果我更改timeLimit為TimeSpan.FromSeconds(3.0)然后我得到這個:
!
!!
True
uj5u.com熱心網友回復:
實際上我通過在時間限制后取消任務找到了解決方案:
public static void ExecuteWithTimeLimit(int timeLimit_milliseconds, Func<bool> codeBlock)
{
var cancellationTokenSource = new CancellationTokenSource();
var cancellationToken = cancellationTokenSource.Token;
Task<bool> task = Task<bool>.Factory.StartNew(() =>
{
try
{
return codeBlock();
}
catch (Exception e)
{
MessageBox.Show(e.Message, "Exeption", MessageBoxButton.OK, MessageBoxImage.Error);
return false;
}
}, cancellationToken);
task.Wait(timeLimit_milliseconds);
cancellationTokenSource.Cancel();
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/403038.html
標籤:
上一篇:我什么時候應該使用Executor而不是ExecutorService
下一篇:JavaFX:“JavaFX應用程式執行緒中的例外java.lang.RuntimeException:java.lang.reflect.InvocationTargetException”Java
