3、Task.Factory.StartNew 將來的任務執行有可能劫持現有任務並殺死其進程.。
a、推薦方法
引入System.Collections.Concurrent 命名空間–線程安全數據結構
把非線程安全的數據結構替換成下面的數據結構即可
BlockingCollection<T> 為實現 IProducerConsumerCollection<T> 的線程安全集合提供阻塞和限制功能。
ConcurrentBag<T> 表示對象的線程安全的無序集合。
ConcurrentDictionary<TKey, TValue> 表示可由多個線程同時訪問的鍵值對的線程安全集合。
ConcurrentQueue<T> 表示線程安全的先進先出 (FIFO) 集合。
ConcurrentStack<T> 表示線程安全的后進先出 (LIFO) 集合。
OrderablePartitioner<TSource> 表示將一個可排序數據源拆分成多個分區的特定方式。
Partitioner 提供針對數組、列表和可枚舉項的常見分區策略。
Partitioner<TSource> 表示將一個數據源拆分成多個分區的特定方式。
b、鎖方法
對於只需要提前響應,而不需要效率的業務可以在內部加鎖。
c、多線程操作會出現線程安全問題,那么可以拆分數據源,然后每一個線程操作單獨的某個數據塊,多線程操作完畢后,在合並數據。
2、實體可能已被修改或刪除異常(20201127)
執行添加日志表數據封裝為異步了Task.Factory.StartNew,
先添加日志表,再執行真刪除另一張表的數據時,
拋出異常:Store update, insert, or delete statement affected an unexpected number of rows (0). Entities may have been modified or deleted since entities were loaded. See http://go.microsoft.com/fwlink/?LinkId=472540 for information on understanding and handling optimistic concurrency exceptions.
提示數據已經被操作過了,臟數據(倉儲判斷的是整個數據,不是判斷的要操作的這一張表是否臟數據),當然還有其他多種不能操作數據的異常。
處理,本次添加日志不使用Task,本次日志需要完整記錄才不會數據丟失。
1、數據庫連接對象斷開問題(20200927)
場景:訂單生成之后,許多后續操作使用Task.Factory.StartNew進行,例如調用,推薦人所推薦用戶下單后,增加其計算優惠券推薦人數量。Task.Factory.StartNew偶爾拋出異常:System.InvalidOperationException: ExecuteReader 要求已打開且可用的 Connection。連接的當前狀態為已關閉。
原因:
1、Task.Factory.StartNew中調用的是創建訂單線程Order_MainBLL類的屬性this.DBSession,去執行業務。也就是使用了同一個數據庫連接對象this.DbContext。
2、Task.Factory.StartNew創建了任務,務開始時,原創建訂單業務結束時,關閉了數據庫連接對象。
處理:
使用不同的數據庫連接對象。
var _DBSession= new Order_MainBLL().DBSession;
try
{
_DBSession.IOrder_MainDAL.SetOrderSampleConfirmList(oid,isRepeat:1);
}
catch (Exception ex)
{
LogHelper.Instance.Error("余額支付后生成待確認出錯:", ex);
}