好了,所以首先我的問題實際上是兩個問題:
- 需要確保,如果前臺應用程序正在運行,後臺進程將不會運行
- 需要確保只有一個線程可以立即訪問數據庫,並且這需要在各個流程中工作,以迎合後臺進程正在啓動時前臺應用程序啓動的情況(公認罕見但可能)。
基於在this thread所做的出色工作,我創建了幾個課程來提供幫助。
爲了解決問題(1),I創建的SingleInstanceSynchroniser:
/// <summary>
/// Used to ensure only one instance (foreground app or background app) runs at once
/// </summary>
public class SingleInstanceSynchroniser : IDisposable
{
private bool hasHandle = false;
Mutex mutex;
private void InitMutex()
{
string mutexId = "Global\\SingleInstanceSynchroniser";
mutex = new Mutex(false, mutexId);
}
public SingleInstanceSynchroniser()
{
InitMutex();
hasHandle = mutex.WaitOne(0);
}
public void Dispose()
{
if (hasHandle && mutex != null)
mutex.ReleaseMutex();
}
public bool HasExclusiveHandle { get { return hasHandle; } }
}
用法:
在App.xaml.cs:
...
SingleInstanceSynchroniser singleInstanceSynchroniser;
public App()
{
singleInstanceSynchroniser = new SingleInstanceSynchroniser();
...
在ScheduledAgent.cs:
SingleInstanceSynchroniser singleInstanceSynchroniser;
protected override void OnInvoke(ScheduledTask task)
{
singleInstanceSynchroniser = new SingleInstanceSynchroniser();
if (singleInstanceSynchroniser.HasExclusiveHandle)
{
//Run background process
...
}
else
{ //Do not run if foreground app is running
NotifyComplete();
}
}
要解決問題(2),我創建了SingleAccessSynchroniser:
/// <summary>
/// Used to ensure only one call is made to the database at once
/// </summary>
public class SingleAccessSynchroniser : IDisposable
{
public bool hasHandle = false;
Mutex mutex;
private void InitMutex()
{
string mutexId = "Global\\SingleAccessSynchroniser";
mutex = new Mutex(false, mutexId);
}
public SingleAccessSynchroniser() : this(0)
{ }
public SingleAccessSynchroniser(int TimeOut)
{
InitMutex();
if (TimeOut <= 0)
hasHandle = mutex.WaitOne();
else
hasHandle = mutex.WaitOne(TimeOut);
if (hasHandle == false)
throw new TimeoutException("Timeout waiting for exclusive access on SingleInstance");
}
public void Release()
{
if (hasHandle && mutex != null)
{
mutex.ReleaseMutex();
hasHandle = false;
}
}
public void Dispose()
{
Release();
}
}
用法:在所有的數據庫調用:
using (var dbSync = new SingleAccessSynchroniser())
{
//Execute your database calls
}
這已經可靠了幾個星期,現在運行。希望別人認爲它有用。
如果在前臺應用兩個線程使同時數據庫請求,那麼你得到這些錯誤之一:「因爲在另一個線程的操作尚未完成無法執行操作」 出現InvalidOperationException 出現InvalidOperationException 「在調用SubmitChanges期間無法執行此操作。」 我不明白爲什麼在後臺應用程序試圖訪問數據庫時這會有所不同,因此您的併發訪問不應該成爲問題的意見是一點點混亂? 我找到了解決這個問題的辦法。當我得到一個空閒時間,我會張貼在這裏:) –