10

ASP.NET Core 如何偵測用戶端已斷線並自動取消非同步方法執行

 3 years ago
source link: https://blog.miniasp.com/post/2021/08/14/How-to-Cancel-a-Task-when-Client-Disconnected-in-ASPNET-Core
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client
ASP.NET Core 如何偵測用戶端已斷線並自動取消非同步方法執行

我今天在「C# 開發實戰:非同步程式開發技巧」課程中有學員提問,如何偵測用戶端已斷線並自動取消非同步方法執行。事實上 ASP.NET (.NET Framework) 與 ASP.NET Core 的實作方式不太一樣,由於 ASP.NET Core 在非同步的支援上遠比 .NET Framework 優秀許多,因此實作上也確實比較容易些。今天這篇文章我就來分享 ASP.NET Core 的實作方式,幫助你有效偵測用戶端已斷線,並自動取消非同步方法執行。

在 ASP.NET Core 中,直接就有個 Request.HttpContext.RequestAborted 屬性可用,而這個屬性的型別恰恰就是 System.Threading.CancellationToken 結構,就是這麼佛心來著! 😍

由於幾乎所有的非同步方法,都有個 CancellationToken 參數可以傳入,今後你不需要特別建立一個 CancellationTokenSource 來自行管理取消非同步的判斷,直接把 Request.HttpContext.RequestAborted 拿去用即可。例如:

  • 實作一個寫入 512MB 檔案,並在用戶端斷線的時候,立即停止寫入,並刪除寫入到一半的檔案

    const string filePath = @"G:\big-file.log";
    try
    {
        await System.IO.File.WriteAllTextAsync(filePath,
                string.Join("", Enumerable.Repeat("A", 1024 * 1024 * 500)),
                Request.HttpContext.RequestAborted);
    }
    catch (TaskCanceledException) when (System.IO.File.Exists(filePath))
    {
        System.IO.File.Delete(filePath);
    }
    

    上述 try/cache 的 when 是 C# 6.0 的例外篩選條件語法,當例外發生條件成立(有檔案存在)才會刪除檔案。

  • 透過 EF Core 5.0 寫入 100 萬筆資料,並在用戶端斷線的時候 Rollback 所有寫到一半的資料

    由於 DbContext.SaveChangesAsync 方法本身就預設包含了交易處理,因此當 CancellationToken 進入取消狀態的時候,寫入到一半的交易就會自動 Rollback,不會殘留髒資料。

    for (int i = 0; i < 1_000_000; i++)
    {
        var d = new Department();
        d.InjectFrom(Department);
    
        _context.Department.Add(d);
    }
    
    await db.SaveChangesAsync(Request.HttpContext.RequestAborted);
    
    if (Request.HttpContext.RequestAborted.IsCancellationRequested)
    {
        // 如果你想在最後檢查用戶端是否斷線,如果斷線可以在這裡進行一些髒資料清理動作!
    }
    

    db.SaveChangesAsync() 這個 Task 被取消的時候會拋出 System.Threading.Tasks.TaskCanceledException 例外,不過由於使用者已經斷線,因此他也不可能看到任何錯誤訊息,但 ASP.NET Core 的 ILogger 會詳實的記錄到這個例外狀況,你可以視情況決定要不要隱藏這些記錄。

有了上述兩個例子,我想應該足以讓你應付所有類似的狀況! 😎


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK