Windows Phone 資料庫並行訪問Windows Phone 資料庫並行訪問

來源:互聯網
上載者:User
Windows Phone 資料庫並行訪問 

原文連結:http://queconejo.wordpress.com/2011/09/04/windows-phone-mango-and-concurrent-database-access/

by

 

Most windows phone developers might already know that the Mango release has a new  API For local database access.

大多數windows phone開發人員可能已經瞭解到Mango已經發布了一系列全新的關於本機資料庫訪問的API。

Typically, windows phone developers are also familiar with asynchronous programming. E.g. when requesting a resource from the internet, the operation will complete on a different thread than it was started on.

通常windows phone開發人員對於非同步編程非常熟悉了。 例如,當請求網路資源時,訪問操作將在與發起訪問不同的縣城上完成。

What caught my attention is that the 2 don’t work well together.

這二者工作工作起來並非一帆風順,這引起了我注意的。

Example

If you download multiple resources from the internet and store these in a local database, it might well be that one operation attempts to store its resource, while another operation is not finished storing another. This can result in one of the exceptions below:

如果你從網路下載多個資源並將其存入本地DB,可能的情況是,你試圖將一個儲存資源進入本地DB,然而其他儲存資源的過程卻並沒有結束。這種情況下將導致下述異常:

  • InvalidOperationException “The operation cannot be performed because an operation on another thread has not been completed.”
  • InvalidOperationException “The operation cannot be performed during a call to SubmitChanges.”

These exceptions are not limited to storing data in the database, they will also occur when trying to read, update, delete or simply calling SubmitChanges.

不止往本地DB儲存資料,當你試圖讀取,更新,刪除或只是SubmitChanges時都會產生上訴異常。

Bottomline

When interacting with data in your local database, It will be up to you as a developer to make sure that you are none of it happens at the same time (=concurrently).

因此,當試圖擷取本地DB的資料時,你應當負起確保這些操作不會並發執行的責任來。

If you are using a foreach-loop when reading data from the database, there is reason for additional caution. You wont be able to do anything with the database until your foreach loop is completed.

當使用foreach迴圈讀取資料時,應當小心了。在foreach完成之前,不應當進行其他的資料庫操作。

UI Thread

One way to unsure(疑為ensure) that operations do not happen concurrently is to execute all of them on the same thread. However, the only thread that allows us to interrupt it and execute something in between other work is the UI Thread. And for performance reasons it doesn’t make sense to borrow time from the UI Thread to solve this problem.

確保不會並發執行的一個方法是使這些操作都在一個線程中執行。然而,唯一允許我們中斷它並執行這些操作的線程是UI線程。然而處於效能考慮,實在不應該爭搶UI線程的寶貴已耗用時間。

AutoResetEvent

A reasonably good solution can be implemented using the AutoResetEvent class (from the System.Threading namespace).

另一個比較恰當的解決方案就是使用AutoResetEvent。

The AutoResetEvent works like a revolting door for threads. It guarantees that no 2 threads can be “inside” at the same time: If a thread runs into such an AutoResetEvent, it will first have to wait for its turn and when its done it allows 1 other thread to take a turn.

AutoResetEvent對於線程就像一扇令人討厭的門。它可以保證同一時刻只會有一個線程同時在門裡邊。當線程遇到AutoResetEvent,它首先必須等待(wait)。

We’ll have to make sure that all threads will go through the same “revolting door” and therefore it makes sense to create one as a static variable:

我們必須確保所有線程通過這扇令人討厭的“門”,因此有必要建立一個靜態變數:

//true means that the first thread that will be waiting can passpublic static AutoResetEvent OperationOnDatabase         = new AutoResetEvent(true); 

Next we’ll need to make sure that any code that will interact with the DataContext will wait for its turn and allow another to take his turn once done.

我們應該確保在訪問DataContext之前,必須等待被允許執行。

try{    //wait for my turn    OperationOnDatabase.WaitOne();    //interact with the database    //use 'ToArray' to make sure we are indeed done    //with our DataContext before we continue    return DataContext.Items.ToArray();}finally {    //always give my turn away when done.    OperationOnDatabase.Set();}

We should repeat this pattern every time we need to interact with the database.

在進行任何資料庫訪問時,都應該遵循同樣的原則。

Notes

First and foremost, if a thread calls “WaitOne” but never calls “Set” (If a thread takes its turn but doesn’t give it away) no other thread will be able to get past “WaitOne”.

首先,如果線程WaitOne卻沒有其他線程Set,那就永遠無法只需執行了,只能無休止等待。

Just like with a normal revolting door, you could get a bit of a queue if there’s a lot of threads trying to enter at the same time (or threads take a long time “inside”: in between calling “WaitOne” and “Set”).

如果同時又很多線程試圖進入的話,那麼門外必將排起長龍。

The occasional waiting will not impact the application much, it could easily happen during Application start or shut down and is preferable over unhandled exceptions. But it probably makes more sense to wait on a background thread, rather than using the UI thread for this.

短暫等待不會影響程式太多,它可以很容易地發生在應用程式啟動或關閉時,比未處理的異常要好的多。在後台線程等待將比UI線程,更可取。

Relying on this mechanism to perform a large amount of database operations concurrently could have some additional adverse effects. e.g: Other parts of the application could stop working if there is a large number of threads waiting in the threadpool.

依靠這種機制,同時執行大量的資料庫操作的能有一些額外的不利影響,例如,尤其當線程池中有太多線程等待的話,程式其他部分可能會暫停工作。

Conclusion

Using the AutoResetEvent we did manage to get around our problem fairly easily.

使用AutoResetEvent可以很輕易解決我們的問題。

The first downside is that we do need to add and maintain extra code when interacting with the database.

第一個不便是,需要在訪問資料庫是添加並維護額外的代碼。

The second downside is the potential of threads unnecessarily waiting for each other. Especially if we are not even really interested in the result.

其二,線程間可能不必要地互斥等待。尤其當不是很在意結果是。

Next post we’ll look try to find a better solution to our problem and dive some deeper into thread synchronization.

下次,我將試圖尋找一更好的方案並深入剖析下線程同步。(原連結自September 2011未有更新,或許可以繼續期待吧)

原文連結:http://queconejo.wordpress.com/2011/09/04/windows-phone-mango-and-concurrent-database-access/

by

 

Most windows phone developers might already know that the Mango release has a new  API For local database access.

大多數windows phone開發人員可能已經瞭解到Mango已經發布了一系列全新的關於本機資料庫訪問的API。

Typically, windows phone developers are also familiar with asynchronous programming. E.g. when requesting a resource from the internet, the operation will complete on a different thread than it was started on.

通常windows phone開發人員對於非同步編程非常熟悉了。 例如,當請求網路資源時,訪問操作將在與發起訪問不同的縣城上完成。

What caught my attention is that the 2 don’t work well together.

這二者工作工作起來並非一帆風順,這引起了我注意的。

Example

If you download multiple resources from the internet and store these in a local database, it might well be that one operation attempts to store its resource, while another operation is not finished storing another. This can result in one of the exceptions below:

如果你從網路下載多個資源並將其存入本地DB,可能的情況是,你試圖將一個儲存資源進入本地DB,然而其他儲存資源的過程卻並沒有結束。這種情況下將導致下述異常:

  • InvalidOperationException “The operation cannot be performed because an operation on another thread has not been completed.”
  • InvalidOperationException “The operation cannot be performed during a call to SubmitChanges.”

These exceptions are not limited to storing data in the database, they will also occur when trying to read, update, delete or simply calling SubmitChanges.

不止往本地DB儲存資料,當你試圖讀取,更新,刪除或只是SubmitChanges時都會產生上訴異常。

Bottomline

When interacting with data in your local database, It will be up to you as a developer to make sure that you are none of it happens at the same time (=concurrently).

因此,當試圖擷取本地DB的資料時,你應當負起確保這些操作不會並發執行的責任來。

If you are using a foreach-loop when reading data from the database, there is reason for additional caution. You wont be able to do anything with the database until your foreach loop is completed.

當使用foreach迴圈讀取資料時,應當小心了。在foreach完成之前,不應當進行其他的資料庫操作。

UI Thread

One way to unsure(疑為ensure) that operations do not happen concurrently is to execute all of them on the same thread. However, the only thread that allows us to interrupt it and execute something in between other work is the UI Thread. And for performance reasons it doesn’t make sense to borrow time from the UI Thread to solve this problem.

確保不會並發執行的一個方法是使這些操作都在一個線程中執行。然而,唯一允許我們中斷它並執行這些操作的線程是UI線程。然而處於效能考慮,實在不應該爭搶UI線程的寶貴已耗用時間。

AutoResetEvent

A reasonably good solution can be implemented using the AutoResetEvent class (from the System.Threading namespace).

另一個比較恰當的解決方案就是使用AutoResetEvent。

The AutoResetEvent works like a revolting door for threads. It guarantees that no 2 threads can be “inside” at the same time: If a thread runs into such an AutoResetEvent, it will first have to wait for its turn and when its done it allows 1 other thread to take a turn.

AutoResetEvent對於線程就像一扇令人討厭的門。它可以保證同一時刻只會有一個線程同時在門裡邊。當線程遇到AutoResetEvent,它首先必須等待(wait)。

We’ll have to make sure that all threads will go through the same “revolting door” and therefore it makes sense to create one as a static variable:

我們必須確保所有線程通過這扇令人討厭的“門”,因此有必要建立一個靜態變數:

//true means that the first thread that will be waiting can passpublic static AutoResetEvent OperationOnDatabase         = new AutoResetEvent(true); 

Next we’ll need to make sure that any code that will interact with the DataContext will wait for its turn and allow another to take his turn once done.

我們應該確保在訪問DataContext之前,必須等待被允許執行。

try{    //wait for my turn    OperationOnDatabase.WaitOne();    //interact with the database    //use 'ToArray' to make sure we are indeed done    //with our DataContext before we continue    return DataContext.Items.ToArray();}finally {    //always give my turn away when done.    OperationOnDatabase.Set();}

We should repeat this pattern every time we need to interact with the database.

在進行任何資料庫訪問時,都應該遵循同樣的原則。

Notes

First and foremost, if a thread calls “WaitOne” but never calls “Set” (If a thread takes its turn but doesn’t give it away) no other thread will be able to get past “WaitOne”.

首先,如果線程WaitOne卻沒有其他線程Set,那就永遠無法只需執行了,只能無休止等待。

Just like with a normal revolting door, you could get a bit of a queue if there’s a lot of threads trying to enter at the same time (or threads take a long time “inside”: in between calling “WaitOne” and “Set”).

如果同時又很多線程試圖進入的話,那麼門外必將排起長龍。

The occasional waiting will not impact the application much, it could easily happen during Application start or shut down and is preferable over unhandled exceptions. But it probably makes more sense to wait on a background thread, rather than using the UI thread for this.

短暫等待不會影響程式太多,它可以很容易地發生在應用程式啟動或關閉時,比未處理的異常要好的多。在後台線程等待將比UI線程,更可取。

Relying on this mechanism to perform a large amount of database operations concurrently could have some additional adverse effects. e.g: Other parts of the application could stop working if there is a large number of threads waiting in the threadpool.

依靠這種機制,同時執行大量的資料庫操作的能有一些額外的不利影響,例如,尤其當線程池中有太多線程等待的話,程式其他部分可能會暫停工作。

Conclusion

Using the AutoResetEvent we did manage to get around our problem fairly easily.

使用AutoResetEvent可以很輕易解決我們的問題。

The first downside is that we do need to add and maintain extra code when interacting with the database.

第一個不便是,需要在訪問資料庫是添加並維護額外的代碼。

The second downside is the potential of threads unnecessarily waiting for each other. Especially if we are not even really interested in the result.

其二,線程間可能不必要地互斥等待。尤其當不是很在意結果是。

Next post we’ll look try to find a better solution to our problem and dive some deeper into thread synchronization.

下次,我將試圖尋找一更好的方案並深入剖析下線程同步。(原連結自September 2011未有更新,或許可以繼續期待吧)

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.