免费视频淫片aa毛片_日韩高清在线亚洲专区vr_日韩大片免费观看视频播放_亚洲欧美国产精品完整版

打開APP
userphoto
未登錄

開通VIP,暢享免費電子書等14項超值服

開通VIP
async/await Task Timeout

在日常的電腦使用過程中,估計最難以忍受的就是軟件界面“卡住”“無響應(yīng)”,在我有限的開發(fā)生涯中一直都是在挑戰(zhàn)
它。在WPF中,主線程即UI線程,當(dāng)我們在UI線程中執(zhí)行一個很耗時的操作,以至于UI線程沒能繼續(xù)繪制窗體,這時給人
的感覺就是“卡住”了。

很耗時的操作分為2種

  • 復(fù)雜計算

  • I/O操作

為了有一個良好的用戶操作體驗,我們都會使用異步方法,在另外一個線程中處理耗時的操作,當(dāng)操作結(jié)束時,僅僅使用
UI線程更新結(jié)果到界面。.Net中的異步模型也有很多種,園子里有很多,不過用起來很舒服的還是async/await。

async/await 的引入讓我們編寫異步方法更加容易,它的目的就是使得我們像同步方法一樣編寫異步方法。上面鋪墊稍微
啰嗦了點。馬上進入正題,當(dāng)我們在await一個方法時,如果這個方法它是支持超時的,那么當(dāng)超時時是以異常的形式來
通知我們的,這樣await以下的方法就沒有辦法執(zhí)行了。

注意:這里補充下,一個Task超時了,并不意味著這個Task就結(jié)束了,它還是會運行,直到結(jié)束或是發(fā)生異常,一個超 時的Task返回的結(jié)果不應(yīng)該被繼續(xù)使用,應(yīng)該丟棄

提供了超時設(shè)置還好,但是如果這個方法沒有超時設(shè)置,那豈不就是一直在這里傻等?那肯定不,只有自己實現(xiàn)超時,一個
線程是沒有辦法做超時功能的。一般都是一個線程執(zhí)行耗時操作,一個線程來計算超時,并且超時了要以異常的形式通知出來,所以
代碼應(yīng)該是這樣的:

    private async void ButtonBase_OnClick(object sender, RoutedEventArgs e)    {        try        {            await CanTimeoutTask(LongTimeWork, 6000);            textBlock.Text = "XXD";            await CanTimeoutTask(LongTimeWork, 3000);        }        catch (Exception ex)        {        }    }    private async Task CanTimeoutTask(Action action, int timeout)    {        var task1 = Task.Run(action);        var task2 = Task.Delay(timeout);        var firstTask = await Task.WhenAny(task1, task2);        if (firstTask == task2)        {            throw new TimeoutException();        }    }    private void LongTimeWork()    {        Thread.Sleep(5000);    }    

如此看來,已經(jīng)滿足我們的需求了,但是作為一個上進的程序員,這么寫真累啊,能不能提出一個簡單易用的方法出來,
于是上Bing(這兩天有點厭惡百度)搜索,看到這么一篇好像有點意思,自己琢磨著改進了一下,所以有了如下版本:

/// <summary>/// 無返回值 可超時,可取消的Task/// </summary>public class TimeoutTask{    #region 字段    private Action _action;    private CancellationToken _token;    private event AsyncCompletedEventHandler _asyncCompletedEvent;    private TaskCompletionSource<AsyncCompletedEventArgs> _tcs;    #endregion    #region 靜態(tài)方法    public static async Task<AsyncCompletedEventArgs> StartNewTask(Action action, CancellationToken token)    {        return await TimeoutTask.StartNewTask(action, token, Timeout.Infinite);    }    public static async Task<AsyncCompletedEventArgs> StartNewTask(Action action, int timeout)    {        return await TimeoutTask.StartNewTask(action, CancellationToken.None, timeout);    }    public static async Task<AsyncCompletedEventArgs> StartNewTask(Action action, CancellationToken token,        int timeout = Timeout.Infinite)    {        var task = new TimeoutTask(action, token, timeout);        return await task.Run();    }    #endregion    #region 構(gòu)造    protected TimeoutTask(Action action, int timeout) : this(action, CancellationToken.None, timeout)    {    }    protected TimeoutTask(Action action, CancellationToken token) : this(action, token, Timeout.Infinite)    {    }    protected TimeoutTask(Action action, CancellationToken token, int timeout = Timeout.Infinite)    {        _action = action;        _tcs = new TaskCompletionSource<AsyncCompletedEventArgs>();        if (timeout != Timeout.Infinite)        {            var cts = CancellationTokenSource.CreateLinkedTokenSource(token);            cts.CancelAfter(timeout);            _token = cts.Token;        }        else        {            _token = token;        }    }    #endregion    #region 私有方法    /// <summary>    /// 運行    /// </summary>    /// <returns></returns>    private async Task<AsyncCompletedEventArgs> Run()    {        _asyncCompletedEvent += AsyncCompletedEventHandler;        try        {            using (_token.Register(() => _tcs.TrySetCanceled()))            {                ExecuteAction();                return await _tcs.Task.ConfigureAwait(false);            }        }        finally        {            _asyncCompletedEvent -= AsyncCompletedEventHandler;        }    }    /// <summary>    /// 執(zhí)行Action    /// </summary>    private void ExecuteAction()    {        Task.Factory.StartNew(() =>        {            _action.Invoke();            OnAsyncCompleteEvent(null);        });    }    /// <summary>    /// 異步完成事件處理    /// </summary>    /// <param name="sender"></param>    /// <param name="e"></param>    private void AsyncCompletedEventHandler(object sender, AsyncCompletedEventArgs e)    {        if (e.Cancelled)        {            _tcs.TrySetCanceled();        }        else if (e.Error != null)        {            _tcs.TrySetException(e.Error);        }        else        {            _tcs.TrySetResult(e);        }    }    /// <summary>    /// 觸發(fā)異步完成事件    /// </summary>    /// <param name="userState"></param>    private void OnAsyncCompleteEvent(object userState)    {        if (_asyncCompletedEvent != null)        {            _asyncCompletedEvent(this, new AsyncCompletedEventArgs(error: null, cancelled: false, userState: userState));        }    }    #endregion}/// <summary>/// 有返回值,可超時,可取消的Task/// </summary>/// <typeparam name="T"></typeparam>public class TimeoutTask<T>{    #region 字段    private Func<T> _func;    private CancellationToken _token;    private event AsyncCompletedEventHandler _asyncCompletedEvent;    private TaskCompletionSource<AsyncCompletedEventArgs> _tcs;    #endregion    #region 靜態(tài)方法    public static async Task<T> StartNewTask(Func<T> func, CancellationToken token,        int timeout = Timeout.Infinite)    {        var task = new TimeoutTask<T>(func, token, timeout);        return await task.Run();    }    public static async Task<T> StartNewTask(Func<T> func, int timeout)    {        return await TimeoutTask<T>.StartNewTask(func, CancellationToken.None, timeout);    }    public static async Task<T> StartNewTask(Func<T> func, CancellationToken token)    {        return await TimeoutTask<T>.StartNewTask(func, token, Timeout.Infinite);    }    #endregion    #region 構(gòu)造    protected TimeoutTask(Func<T> func, CancellationToken token) : this(func, token, Timeout.Infinite)    {    }    protected TimeoutTask(Func<T> func, int timeout = Timeout.Infinite) : this(func, CancellationToken.None, timeout)    {    }    protected TimeoutTask(Func<T> func, CancellationToken token, int timeout = Timeout.Infinite)    {        _func = func;        _tcs = new TaskCompletionSource<AsyncCompletedEventArgs>();        if (timeout != Timeout.Infinite)        {            var cts = CancellationTokenSource.CreateLinkedTokenSource(token);            cts.CancelAfter(timeout);            _token = cts.Token;        }        else        {            _token = token;        }    }    #endregion    #region 私有方法    /// <summary>    /// 運行Task    /// </summary>    /// <returns></returns>    private async Task<T> Run()    {        _asyncCompletedEvent += AsyncCompletedEventHandler;        try        {            using (_token.Register(() => _tcs.TrySetCanceled()))            {                ExecuteFunc();                var args = await _tcs.Task.ConfigureAwait(false);                return (T)args.UserState;            }        }        finally        {            _asyncCompletedEvent -= AsyncCompletedEventHandler;        }    }    /// <summary>    /// 執(zhí)行    /// </summary>    private void ExecuteFunc()    {        ThreadPool.QueueUserWorkItem(s =>        {            var result = _func.Invoke();            OnAsyncCompleteEvent(result);        });    }    /// <summary>    /// 異步完成事件處理    /// </summary>    /// <param name="sender"></param>    /// <param name="e"></param>    private void AsyncCompletedEventHandler(object sender, AsyncCompletedEventArgs e)    {        if (e.Cancelled)        {            _tcs.TrySetCanceled();        }        else if (e.Error != null)        {            _tcs.TrySetException(e.Error);        }        else        {            _tcs.TrySetResult(e);        }    }    /// <summary>    /// 觸發(fā)異步完成事件    /// </summary>    /// <param name="userState"></param>    private void OnAsyncCompleteEvent(object userState)    {        if (_asyncCompletedEvent != null)        {            _asyncCompletedEvent(this, new AsyncCompletedEventArgs(error: null, cancelled: false, userState: userState));        }    }    #endregion}

使用起來也很方便

    private async void ButtonBase_OnClick(object sender, RoutedEventArgs e)    {        try        {            await TimeoutTask.StartNewTask(LongTimeWork, 6000);            var result = await TimeoutTask<string>.StartNewTask(LongTimeWork2, 2000);            textBlock.Text = result;        }        catch (Exception ex)        {        }    }    private void LongTimeWork()    {        Thread.Sleep(5000);    }    private string LongTimeWork2()    {        Thread.Sleep(5000);        return "XXD";    }    

其中有一些很少見的CancellationTokenSource CancellationToken TaskCompletionSource AsyncCompletedEventHandler AsyncCompletedEventArgs
不要怕,MSDN上一會就弄懂了。記錄一下,算是這兩天的研究成果。

本站僅提供存儲服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊舉報。
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
C#中的異步編程--探索await與async關(guān)鍵字的奧妙之處,原來理解和使用異步編程可以這么簡單
python 異步 async/await -1.一文理解什么是協(xié)程
使用Task簡化Silverlight調(diào)用Wcf
異步編程初探async和await
探索c#之Async、Await剖析
異步陷阱之死鎖篇
更多類似文章 >>
生活服務(wù)
分享 收藏 導(dǎo)長圖 關(guān)注 下載文章
綁定賬號成功
后續(xù)可登錄賬號暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點擊這里聯(lián)系客服!

聯(lián)系客服