c#關於同步 /異常/多執行緒/事件 事例

一贴灵發表於2024-08-28

sync 同步

async 非同步 ,要與 await 成對使用

Thread

//計算程式執行時間

StopWatch sw= StopWatch.Start();

轉自:https://codeload.github.com/zhaoxueliang86/WinFormsAsyncAwait/zip/refs/heads/Bilibili

B站 UP主:銀色

using System.Diagnostics;
using System.Text;

namespace WinFormsAsyncAwait
{
    public partial class FormThread : Form
    {
        public FormThread()
        {
            InitializeComponent();

            Data.Books.ForEach(book => { book.EventCompleted += Book_EventCompleted; });
        }
        private void Book_EventCompleted(object? sender, Book.BookEventArgs e)
        {
            AppendLineThread(e.Result!);
        }

        /// <summary>
        /// 同步
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void BtnSync_Click(object sender, EventArgs e)
        {
            Stopwatch sw = Stopwatch.StartNew();    //計時器
            resultTextBox.Clear();
            AppendLine("同步檢索開始......");
            int idx = 0;

            Data.Books.ForEach(book => AppendLine($"{++idx}.{book.Search()}"));

            sw.Stop();
            AppendLine($"同步檢索完成:{Convert.ToSingle(sw.ElapsedMilliseconds) / 1000}秒");
        }
        /// <summary>
        /// 非同步
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private async void BtnAsync_Click(object sender, EventArgs e)
        {
            Stopwatch sw = Stopwatch.StartNew();
            resultTextBox.Clear();
            AppendLine("非同步檢索開始......");
            AppendLine($"ThreadId:{Environment.CurrentManagedThreadId}");

            int idx = 0;

            foreach (var book in Data.Books)
            {
                var task = await Task.Run(book.Search).ConfigureAwait(true);
                
                AppendLineThread($"{++idx}.{task}        ThreadId:{Environment.CurrentManagedThreadId}");
            }

            sw.Stop();
            AppendLineThread($"非同步檢索完成:{Convert.ToSingle(sw.ElapsedMilliseconds) / 1000}秒");
        }
        /// <summary>
        /// 非同步
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void BtnAsyncCallbak_Click(object sender, EventArgs e)
        {
            Stopwatch sw = Stopwatch.StartNew();
            resultTextBox.Clear();
            AppendLine("非同步回撥檢索開始......");
            int idx = 0;

            foreach (var book in Data.Books)
            {
                Task.Run(book.Search).ContinueWith(t => AppendLineThread($"{++idx}.{t.Result}"));
            }

            sw.Stop();
            AppendLine($"非同步回撥檢索完成:{Convert.ToSingle(sw.ElapsedMilliseconds) / 1000}秒");
        }
        /// <summary>
        /// 並行
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private async void BtnConcurrencyAsync_Click(object sender, EventArgs e)
        {
            Stopwatch sw = Stopwatch.StartNew();
            resultTextBox.Clear();
            AppendLine($"並行檢索開始......");
            int idx = 0;

            List<Task<string>> Tasks = new();
            Data.Books.ForEach(book => Tasks.Add(Task.Run(book.Search)));

            var tasks = await Task.WhenAll(Tasks).ConfigureAwait(false);
            foreach (var result in tasks)
            {
                AppendLine($"{++idx}.{result}");
            }
            sw.Stop();
            AppendLine($"並行檢索完成:{Convert.ToSingle(sw.ElapsedMilliseconds) / 1000}秒");
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void BtnConcurrencyCallback_Click(object sender, EventArgs e)
        {
            Stopwatch sw = Stopwatch.StartNew();
            resultTextBox.Clear();
            AppendLine("並行回撥檢索開始......");

            int idx = 0;
            List<Task<string>> Tasks = new();
            foreach (var book in Data.Books)
            {
                Tasks.Add(Task.Run(book.Search));
            }

            Task.WhenAll(Tasks).ContinueWith(t =>
            {
                foreach (var result in t.Result)
                {
                    AppendLine($"{++idx}.{result}");
                }
                sw.Stop();
                AppendLine($"並行回撥檢索完成:{Convert.ToSingle(sw.ElapsedMilliseconds) / 1000}秒");
            });
        }

        private void AppendLine(string text)
        {
            resultTextBox.AppendText(string.IsNullOrEmpty(resultTextBox.Text) ? text : $"{Environment.NewLine}{text}");
            resultTextBox.ScrollToCaret();       //把控制元件內容滾動到當前插入符號位置
            resultTextBox.Refresh();
        }

        private void AppendLineThread(string text)
        {
            this.BeginInvoke(() => AppendLine(text));
        }

        private async void BtnEvent_Click(object sender, EventArgs e)
        {
            Stopwatch sw = Stopwatch.StartNew();
            resultTextBox.Clear();
            AppendLine("檢索開始......");

            List<Task> Tasks = new();
            foreach (var book in Data.Books)
            {
                Tasks.Add(Task.Run(book.SearchEvent));
            }
            await Task.WhenAll(Tasks);
            sw.Stop();
            AppendLine($"檢索完成:{Convert.ToSingle(sw.ElapsedMilliseconds) / 1000}秒");
        }


        private StringBuilder strResult = new();
        private void Test_ConfigureAwait(object sender, EventArgs e)
        {
            bool state = ((Button)sender).Text == "True";
            strResult.Clear();
            strResult.AppendLine($"【{Environment.CurrentManagedThreadId}】主執行緒開始:ConfigureAwait({state.ToString()})");
            
            ChildMethod(state);
            
            strResult.AppendLine($"【{Environment.CurrentManagedThreadId}】主執行緒開始等待");
            
            Thread.Sleep(3000);
            
            strResult.AppendLine($"【{Environment.CurrentManagedThreadId}】主執行緒結束");
            MessageBox.Show("success","提示",MessageBoxButtons.OK,MessageBoxIcon.Information);
        }
        private async void ChildMethod(bool state)
        {
            strResult.AppendLine($"【{Environment.CurrentManagedThreadId}】ChildMethod開始");

            Stopwatch sw = Stopwatch.StartNew();

            await Task.Run(() =>
            {
                strResult.AppendLine($"【{Environment.CurrentManagedThreadId}】子執行緒開始");
                Thread.Sleep(2000);
                strResult.AppendLine($"【{Environment.CurrentManagedThreadId}】子執行緒結束");
            }).ConfigureAwait(state);

            sw.Stop();
            strResult.AppendLine($"【{Environment.CurrentManagedThreadId}】ChildMethod結束{sw.ElapsedMilliseconds}");
        }

        private void BtnPrint_Click(object sender, EventArgs e)
        {
            AppendLine(strResult.ToString());
        }
    }
}

相關文章