2017-04-24 28 views
0

我有一個由EntityFramework表示的數據庫,我在異步任務中向它添加了一個元素。我的方法是在簡化這樣的:非靜態方法中的異步數據庫操作

private async Task SavePoint(Point point) 
    { 
     using (var ctx = new testDBEntities()) 
     { 
      ctx.Points.Add(point); 
      await ctx.SaveChangesAsync(); 
     } 
    } 

但是任務是非靜態的,我用它簡單地調用SavePoint(point);(沒有的await),因爲我並不需要等待完成的任務。我想要的是在後臺保存點,並允許用戶繼續他的工作,並在添加時不做任何事情。

但是我不知道在幾個任務中使用數據庫上下文(當用戶快速添加幾個點時)不會引發數據庫死鎖的競爭條件嗎?它確保互相排斥嗎?

回答

0

在沒有等待的情況下調用SavePoint(point)會在visual studio中導致「Because this call is not awaited, the current method continues to run before the call is completed」警告。在該警告的頁面上指出:

考慮這種情況。

  • 對異步方法的調用啓動異步任務。但是,由於沒有應用等待操作符,程序將繼續而不等待任務完成。

  • 調用方法依賴於電話或最低限度的結果,被調用方法,預計從包含呼叫

  • 什麼與在被叫引起的異常情況發生的方法返回前完成異步方法。在返回任務或任務的方法中引發的異常存儲在返回的任務中。如果您不等待任務或明確檢查異常,則異常將丟失。

在您的情況,您可以移動這樣的,也將努力執行異步

Task.Run(() => SavePoint(point)); 
+0

爲什麼你認爲在'Task.Run'中執行'SavePoint'會更好?會有什麼區別? –

+0

因爲他不想等。它可以是Task.Run()。謝謝我會更新答案 – Eldho

+0

但是,又會有什麼區別?爲什麼比簡單地調用'SavePoint'更好? –

0

你混合不同的關切在一起。

我想要的是在後臺保存一個點,並允許用戶繼續他的工作,並且當它被添加時什麼也不做。

您可以標記您的事件處理程序(我假設您從事件處理程序執行您的邏輯)異步,然後等待您的數據庫訪問操作。標記處理程序異步將確保在數據庫操作期間UI不會被阻塞,並且用戶將能夠繼續與UI進行交互。

但是,我想知道如果在幾個任務中使用數據庫上下文(當用戶快速添加幾個點)不會引發數據庫死鎖的競爭條件?它確保互相排斥嗎?

無論您是否使用等待與否UI將不會阻止和用戶將能夠啓動,可能會導致死鎖其他操作。

最好是等待數據庫操作,因爲它使您有可能捕獲異常並重試或通知用戶出現問題。如果您不等待,您將失去有關異常和應用程序狀態的信息不一致。

只是爲了重申,無論您是否使用等待或不使用,如果這是您的擔心,UI將不會被阻止。

4

我使用它只是調用SavePoint(point); (無需等待),因爲我不需要等待任務完成。

確定嗎?如果保存失敗,你甚至不希望知道

您可能最好將請求放入try,並且至少通知用戶它們的更改未保存。

但是,我想知道如果在幾個任務中使用數據庫上下文(當用戶快速添加幾個點)不會引發數據庫死鎖的競爭條件?

它不會造成死鎖,在這種特殊情況下,不存在競爭條件的可能性。這是因爲你的每個數據庫更新只是一個INSERT

請參閱here瞭解EF中處理併發性問題的更一般情況。

+1

只是一個小提示:如果有一個索引要更新並且其他一些操作持有對索引的鎖定,insert可能會導致死鎖。 –

+0

但是,如果我想要一個'SavePoint'調用方法來等待,調用方法也必須是異步的,不是嗎? – Niko

+0

最適合我的是: 'private void AddPoint(Point point){ /* add to interface */ 嘗試waitPoint SavePoint(point); } catch(Exception e){ /*在界面上引發事件通知給pront,但不停止應用程序* } 然而,await只能用於異步,我有一個「永無止境的故事」。 – Niko