新建一個Winfrom專案,加入下面程式碼:
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace 執行緒2
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
Task task1 = new Task(() =>
{
Thread.Sleep(400);
Console.WriteLine("task1");
});
Task task2 = new Task(() =>
{
Thread.Sleep(300);
Console.WriteLine("task2");
});
Task task3 = new Task(() =>
{
Thread.Sleep(200);
Console.WriteLine("task3");
});
Task task4 = new Task(() =>
{
Thread.Sleep(100);
Console.WriteLine("task4");
});
task1.Start();
task2.Start();
task3.Start();
task4.Start();
}
}
}
執行:
由於延時不同,最先執行的Task1,反而最後一個執行完,那麼如果要求從任務1,一直執行到任務4,怎麼寫呢?
程式碼:
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace 執行緒2
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private List<Task> TaskList = new List<Task>();
private void Form1_Load(object sender, EventArgs e)
{
Task task1 = new Task(() =>
{
Thread.Sleep(400);
Console.WriteLine("task1");
});
Task task2 = new Task(() =>
{
Thread.Sleep(300);
Console.WriteLine("task2");
});
Task task3 = new Task(() =>
{
Thread.Sleep(200);
Console.WriteLine("task3");
});
Task task4 = new Task(() =>
{
Thread.Sleep(100);
Console.WriteLine("task4");
});
TaskList.Add(task1);
TaskList.Add(task2);
TaskList.Add(task3);
TaskList.Add(task4);
foreach (Task task in TaskList)
{
task.Start();
task.Wait();
}
}
}
}
執行:
用上面的方法雖然有效,但會阻塞主執行緒,導致winfrom介面卡住,無法操作,下面就用非同步的方法解決問題
程式碼:
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace 執行緒2
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private List<Task> TaskList = new List<Task>();
private void Form1_Load(object sender, EventArgs e)
{
}
private void Button_Calculate_Click(object sender, EventArgs e)
{
Task task1 = new Task(async () =>
{
await Task.Delay(TimeSpan.FromSeconds(4));
Console.WriteLine("task1");
});
Task task2 = new Task(async () =>
{
await Task.Delay(TimeSpan.FromSeconds(3));
Console.WriteLine("task2");
});
Task task3 = new Task(async () =>
{
await Task.Delay(TimeSpan.FromSeconds(2));
Console.WriteLine("task3");
});
Task task4 = new Task(async () =>
{
await Task.Delay(TimeSpan.FromSeconds(1));
Console.WriteLine("task4");
});
TaskList.Add(task1);
TaskList.Add(task2);
TaskList.Add(task3);
TaskList.Add(task4);
foreach (Task task in TaskList)
{
task.Start();
task.Wait();
}
}
}
}
執行:
用非同步方式雖然介面不會卡住,但另一個問題來了,task.wait()方法似乎沒有效果。裡面的任務佇列依然沒有按順序來執行。
經過一段時間的研究,後面我終於找到方法了,用下面的方法既不會卡住UI,也會按照佇列來執行,雖然寫法不是特別好,讀者可以按下面方法自己封裝了。
private void Test()
{
Task.Run(() =>
{
Task t1 = new Task(() => {
Thread.Sleep(2000);
Console.WriteLine("t1");
num = 1;
});
t1.Start();
t1.Wait();
Task t2 = new Task(() => {
Thread.Sleep(1000);
Console.WriteLine("t2");
num = 3;
});
t2.Start();
t2.Wait();
Console.WriteLine("執行緒執行完畢");
});
}
執行:
也可以這樣寫:
private async void Test()
{
await Task.Run(async () =>
{
await Task.Delay(4000);
Trace.WriteLine("第1個執行緒執行");
});
await Task.Run(async () =>
{
await Task.Delay(3000);
Trace.WriteLine("第2個執行緒執行");
});
await Task.Run(async () =>
{
await Task.Delay(2000);
Trace.WriteLine("第3個執行緒執行");
});
}
執行:
對現有程式碼進行封裝:
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace Utils
{
public class TaskQueue
{
/// <summary>
/// 任務列表
/// </summary>
private List<Task> TaskList = null;
/// <summary>
/// 是否在執行任務中
/// </summary>
private bool isPerformTask = false;
/// <summary>
/// 執行完任務的回撥
/// </summary>
public Action CallBack = null;
private static TaskQueue _instance = null;
public static TaskQueue Instance
{
get
{
if (_instance == null)
_instance = new TaskQueue();
return _instance;
}
}
/// <summary>
/// 新增任務
/// </summary>
/// <param name="task"></param>
public void AddTask(Task task)
{
if (isPerformTask)
{
Console.WriteLine("[TaskQueue]任務正在執行中,此時不能做賦值操作");
return;
}
if (task != null)
{
TaskList.Add(task);
}
}
/// <summary>
/// 執行任務
/// </summary>
public void PerformTask()
{
if (isPerformTask)
{
Console.WriteLine("[TaskQueue]任務正在執行中,不可重複呼叫");
return;
}
if (TaskList == null || TaskList.Count == 0)
{
Console.WriteLine("[TaskQueue]任務列表為空");
return;
}
Task.Run(() =>
{
isPerformTask = true;
foreach (Task item in TaskList)
{
item.Start();
item.Wait();
}
TaskList.Clear();
isPerformTask = false;
if (CallBack != null) CallBack();
});
}
private TaskQueue()
{
TaskList = new List<Task>();
}
}
}
呼叫:
Task task1 = new Task(() =>
{
Thread.Sleep(1000);
Console.WriteLine("t1");
});
Task task2 = new Task(() =>
{
Thread.Sleep(2000);
Console.WriteLine("t2");
});
Task task3 = new Task(() =>
{
Console.WriteLine("t3");
});
Action callback = () =>
{
Console.WriteLine("所有任務執行完成");
};
TaskQueue.Instance.AddTask(task1);
TaskQueue.Instance.AddTask(task2);
TaskQueue.Instance.AddTask(task3);
TaskQueue.Instance.CallBack = callback;
TaskQueue.Instance.PerformTask();
執行:
如果你這個貼文對你有用,歡迎給我點贊 + 留言,謝謝
end