1. 程式人生 > >winform防止介面卡死的三種方法

winform防止介面卡死的三種方法

在程式設計過程中經常會遇到耗時操作,這個時候如果不採取一些必要的非同步操作,就會導致介面的卡死,這裡以winform為例子,介紹三種方法防止介面卡死,對這幾個方法稍加修改同樣適用於wpf,silverlight等程式

首先給出一個函式模擬耗時操作

1使用委託+QueueUserWorkItem

delegate void ChangeInvoke(int num) ;
private void ChangeNum(int num)
        {
            MessageBox.Show(num.ToString());
        }
private void DoSomeThing(object state)
        {
            int i=0;
            for (int i = 0; i < int.MaxValue-1; i++)
            {
                i++;
            }
            ChangeInvoke change = new ChangeInvoke(ChangeNum);
            this.Invoke(change,new object[]{i});
        }

以下是通過QueueUserWorkItem非同步呼叫

ThreadPool.QueueUserWorkItem(DoSomeThing);
其實很簡單,也就是一句程式碼的事。

2使用Task

首先還是模擬耗時操作

private int TaskTest(int num,CancellationToken token) {
           // num = 0;
            for (int i = 0; i < int.MaxValue-10; i++)
            {
                token.ThrowIfCancellationRequested();
                num++;
            }
            return num;
        }
這個耗時操作因為添加了CancellationToken,因而支援取消

接著定義耗時操作完成之後的操作

 private void ShowResult(Task<Int32> t)
        {
            try
            {
                MessageBox.Show(t.Result.ToString());
            }
            catch(AggregateException ex)
            {
                MessageBox.Show("操作中斷!");
            }
        }
最後是利用進行非同步操作
Task<Int32> task = new Task<Int32>(n=>TaskTest(10,cancelSource.Token),0);
task.Start();
Task tsk = task.ContinueWith(t => ShowResult(t));
如此程式將會在耗時操作結束是呼叫ShowResult函式

以上兩種方法使用到Task 和QueueUserWorkItem,因為之前已經有寫過文章詳細的介紹過,這裡就不細說了,有興趣的可以翻閱本人的前幾篇文章,有做比較詳細的介紹。

3利用APM進行非同步呼叫

依然是耗時操作

 private int DoSomeThing(int num)
        {
            for (int i = 0; i < int.MaxValue - 10; i++)
            {
                num++;
            }
            return num;
        }
下面是耗時操作結束後的操作
 private void APMDone(IAsyncResult result)
        {
            var sumDelegate = (Func<int, int>)result.AsyncState;
            try
            {
                int sumResult = sumDelegate.EndInvoke(result);
                MessageBox.Show(sumResult.ToString());
            }
            catch(Exception e)
            {
                MessageBox.Show(e.Message);
            }
        }
最後是呼叫的方法
Func<int, int> SumDelegate = TaskTest2;
SumDelegate.BeginInvoke(0, APMDone, SumDelegate);

本人才疏學淺,這裡僅僅對這些方法做一個簡單的總結,其內部的原理就不細說了,免得被高手拍磚,如有疏漏之處,還望指出,如果對於你有一定的參考價值,那真是莫大的榮幸