我正在與實體框架的WPF應用程序(MVVM)。我想在給定的時間間隔內查詢SQL服務器上的一個表,以向用戶顯示更新的DB值。爲此我成立了一個計時器在我的ViewModel像這樣:System.Timers.Timer.SynchronizingObject ManagedThreadId不是從主線程
RefreshTimer = new System.Timers.Timer(2000.0);
RefreshTimer.Enabled = true;
RefreshTimer.SynchronizingObject = new Synchronizer();
RefreshTimer.Elapsed += RefreshTimer_Elapsed;
,其中同步是ISynchronizeInvoke的實現:
internal class Synchronizer : ISynchronizeInvoke
{
private object _sync = new object();
public bool InvokeRequired { get { return true; } }
public IAsyncResult BeginInvoke(Delegate method, object[] args)
{
var result = new SimpleAsyncResult();
ThreadPool.QueueUserWorkItem(delegate {
result.AsyncWaitHandle = new ManualResetEvent(false);
try
{
result.AsyncState = Invoke(method, args);
}
catch (Exception exception)
{
result.Exception = exception;
}
result.IsCompleted = true;
});
return result;
}
public object EndInvoke(IAsyncResult result)
{
if (!result.IsCompleted)
{
result.AsyncWaitHandle.WaitOne();
}
return result.AsyncState;
}
public object Invoke(Delegate method, object[] args)
{
lock (_sync)
{
return method.DynamicInvoke(args);
}
}
}
internal class SimpleAsyncResult : IAsyncResult
{
object _state;
public bool IsCompleted { get; set; }
public WaitHandle AsyncWaitHandle { get; internal set; }
public object AsyncState
{
get
{
if (Exception != null)
{
throw Exception;
}
return _state;
}
internal set
{
_state = value;
}
}
public bool CompletedSynchronously { get { return IsCompleted; } }
internal Exception Exception { get; set; }
}
如果我理解正確的話,則SynchronizingObject的就應該召集所經過的事件SynchronizingObject創建的線程。在我的情況下,這是主線程。現在考慮下面的代碼來處理事件:
private void RefreshTimer_Elapsed(object sender, ElapsedEventArgs e)
{
System.Diagnostics.Debug.WriteLine($"RefreshTimer ManagedThreadID: {Thread.CurrentThread.ManagedThreadId}");
RefreshTimer.SynchronizingObject.Invoke((Action)(() => { TestMethod(); }), null);
}
public void TestMethod()
{
System.Diagnostics.Debug.WriteLine($"TestMethod ManagedThreadID: {Thread.CurrentThread.ManagedThreadId}");
}
的TestMethod的是我將更新/重裝我的實體對象,以便查看會自動顯示最新的數據。當我嘗試這樣做,我得到一個InvalidOperationException異常,說明,因爲不同的線程擁有它調用線程不能訪問該對象
輸出是:
RefreshTimer ManagedThreadID: 5
TestMethod ManagedThreadID: 5
RefreshTimer ManagedThreadID: 4
TestMethod ManagedThreadID: 4
RefreshTimer ManagedThreadID: 8
TestMethod ManagedThreadID: 8
而且我懷疑這是我得到的理由以上例外。我希望可以將輸出爲:
RefreshTimer ManagedThreadID: 5
TestMethod ManagedThreadID: 1
RefreshTimer ManagedThreadID: 4
TestMethod ManagedThreadID: 1
RefreshTimer ManagedThreadID: 8
TestMethod ManagedThreadID: 1
誰能告訴我,我做錯了什麼,以及如何我可以得到SynchronizingObject.Invoke方法在主線程上執行?
你不應該使用一個工作線程定時器GUI代碼 – MickyD