我有一組在外部硬體上運行的異步測驗。
我可以按順序運行它們,但因為所有這些測驗都有副作用,我希望能夠對它們進行洗牌并一遍又一遍地運行它們。
當我將它們放在一個串列中并嘗試在之后等待每個時,它們都并行運行,而不是 1 個運行。
我希望能夠洗牌串列,然后按順序運行它們。
我如何List<Task<bool>
按順序運行測驗 ( ),同時將它們保存在串列中,以便我可以隨機播放串列?
private async void RunVisca()
{
Ptz ptz = new Ptz(SelectedComPort, (byte)(1), SelectedBaudRate, Node.DeviceType.PTZ);
UpdateResults("VISCA TEST START\n\n");
// Method 1: Correct - Runs in order
await VTestDriveClosedLoop(ptz, true);
await VTestDriveClosedLoop(ptz, false);
await VTestLimitsCl(ptz, 125, 20);
await VTestLimitsOl(ptz, 125, 20);
// Method 2: Incorrect - Runs in parallel
List<Task<bool>> tests = new List<Task<bool>>();
tests.Add(VTestDriveClosedLoop(ptz, true));
tests.Add(VTestDriveClosedLoop(ptz, false));
tests.Add(VTestLimitsCl(ptz, 125, 20));
tests.Add(VTestLimitsOl(ptz, 125, 20));
// Tasks all run in parallel here - should they not run in order?
foreach(Task<bool> test in tests)
{
_ = await test.ConfigureAwait(true);
}
UpdateResults("\nTEST COMPLETE\n\n");
}
uj5u.com熱心網友回復:
基于任務的異步模式 (TAP) 模式意味著呼叫async
回傳 a的方法Task
將回傳熱任務。
Task
處于熱狀態的A已經啟動。這可以通過檢查Task.Status
屬性來證明,該屬性永遠不會是TaskStatus.Created
。
一個寒冷的任務將有一個Task.Status
財產TaskStatus.Created
和才會開始運行的時候Start()
被呼叫的實體。
創建冷任務的唯一方法是使用Task
/Task<T>
各自的公共建構式。
由于您的任務是通過異步方法回傳的,因此當它們回傳給您時它們已經在運行。
要按順序而不是并行運行它們,除非前一個任務已完成,否則您不能一個接一個地創建它們。為確保這一點,您必須分別處理await
它們。
這導致方法 1 是按順序而不是并行運行熱任務的正確方法。
await VTestDriveClosedLoop(ptz, true);
await VTestDriveClosedLoop(ptz, false);
await VTestLimitsCl(ptz, 125, 20);
await VTestLimitsOl(ptz, 125, 20);
方法 2/3 不正確,因為它將并行運行您的任務。
您正在將從您的async
方法回傳的熱門任務添加到您的串列中,而無需等待它們。在您繼續將下一個任務添加到串列之前,它們將已經開始運行。
第一任務是不等待,因此第二次任務后立即啟動,不管任務完成1與否。
不等待第二個任務,所以第三個任務等。
使用方法 2/3,它們將始終并行運行。
tests.Add(VTestDriveClosedLoop(ptz, true));
tests.Add(VTestDriveClosedLoop(ptz, false));
真正的問題是如何按順序運行冷任務,以便我們可以將它們存盤在串列中,同時利用延遲執行,直到我們遍歷我們的串列。
解決方案是存盤委托,這將觸發以下任務建構式:
public Task (Func<TResult> function);
這將創建冷任務,讓您Task
在Func<Task<bool>>
呼叫時運行:
var tests = new List<Func<Task<bool>>>();
tests.Add(() => VTestDriveClosedLoop(ptz, true));
tests.Add(() => VTestDriveClosedLoop(ptz, false));
tests.Add(() => VTestLimitsCl(ptz, 125, 20));
tests.Add(() => VTestLimitsOl(ptz, 125, 20));
foreach (var test in tests) {
await test();
}
下面的演示程式將清楚地顯示按順序運行與并行運行的任務。
class Program
{
private static async Task Main(string[] args)
{
// 1... 2... 3... 4...
var tasksThatRunInOrder = new List<Func<Task<bool>>>();
tasksThatRunInOrder.Add(() => Test("1"));
tasksThatRunInOrder.Add(() => Test("2"));
tasksThatRunInOrder.Add(() => Test("3"));
tasksThatRunInOrder.Add(() => Test("4"));
foreach (var test in tasksThatRunInOrder)
await test();
// 1, 2, 3, 4
var testsThatRunInParallel = new List<Task<bool>>();
testsThatRunInParallel.Add(Test("1"));
testsThatRunInParallel.Add(Test("2"));
testsThatRunInParallel.Add(Test("3"));
testsThatRunInParallel.Add(Test("4"));
foreach (var test in testsThatRunInParallel)
await test;
}
private static async Task<bool> Test(string x)
{
Console.WriteLine(x);
await Task.Delay(1000);
return true;
}
}
uj5u.com熱心網友回復:
任務在創建時開始。由于您是同時創建所有這些而不等待它們中的任何一個,因此它們將以不確定的并行方式執行。我想也許您想改為存盤代表。這些在被呼叫之前不會執行。
var tests = new List<Func<Task<bool>>>();
tests.Add( () => VTestDriveClosedLoop(ptz, true) );
tests.Add( () => VTestDriveClosedLoop(ptz, false) );
tests.Add( () => VTestLimitsCl(ptz, 125, 20) );
tests.Add( () => VTestLimitsOl(ptz, 125, 20) );
foreach(var test in tests)
{
_ = await test();
}
uj5u.com熱心網友回復:
您可以創建一個串列,在其中隨機化要運行的順序,然后相應地呼叫創建任務的函式。例如:
static async Task RunTasks()
{
Random rng = new Random();
var order = new List<int>() { 1, 2 };
var shuffledOrder = order.OrderBy(a => rng.Next()).ToList();
foreach (var i in shuffledOrder)
{
switch (i)
{
case 1:
await LoadFile1();
break;
case 2:
await LoadFile2();
break;
}
}
}
uj5u.com熱心網友回復:
嘗試在不分配給一次性變數的情況下等待。
uj5u.com熱心網友回復:
的呼叫鏈怎么樣ContinueWith
?
Task.Run(async () =>
{
await VTestDriveClosedLoop(ptz, true);
}).ContinueWith(async (_) =>
{
await VTestDriveClosedLoop(ptz, false);
}).ContinueWith(async (_) =>
{
await VTestLimitsCl(ptz, 125, 20);
}).ContinueWith(async (_) =>
{
await VTestLimitsOl(ptz, 125, 20);
});
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/318807.html
下一篇:AsyncFunction().GetAwaiter().GetResult()和Task.Run(()=>AsyncFunction).GetAwaiter().GetResult()有什么區