我有一個wcf客戶端,在與wcf服務進行一些複雜的交互之前,請執行一項簡單的服務檢查以確保活着。由於連接失敗的超時時間爲一分鐘,我想異步實現此檢查。如何在與其他線程上的服務器通信時保持我的WPF UI響應?
這是我有:
//Method on the main UI thread
public void DoSomeComplicatedInteraction()
{
If(ConnectionIsActive()) DoTheComplicatedInteraction();
}
private bool ConnectionIsActive()
{
//Status is a Textblock on the wpf form
Status.Text = "Checking Connection";
var ar = BeginConnectionIsActive();
while (!ar.IsCompleted)
{
Status.Text += ".";
Thread.Sleep(100);
}
EndConnectionIsActive(ar);
//IsConnected is a boolean property
return IsConnected;
}
private IAsyncResult BeginConnectionIsActive()
{
//checkConnection is Func<bool> with value CheckConnection
return checkConnection.BeginInvoke(null,checkConnection);
}
private void EndConnectionIsActive(IAsyncResult ar)
{
var result=((Func<bool>)ar.AsyncState).EndInvoke(ar);
IsConnected = result;
}
private bool CheckConnection()
{
bool succes;
try
{
//synchronous operation
succes=client.Send(RequestToServer.GetPing()).Succes;
}
catch
{
succes = false;
}
return succes;
}
這工作。只有當我嘗試通過在服務器的Send方法中添加Thread.Sleep來模擬緩慢的服務器響應時,UI變得無響應。此外,狀態文本塊的文本沒有明顯更新。 看來我需要某種Application.DoEvents方法。 還是我需要一種不同的方法?編輯: 確實,不同的方法是必要的。使用Thread.Sleep將阻止UI,當我們在主UI線程上調用時。 這是我如何解決它:
//Method on the main UI thread
public void DoSomeComplicatedInteraction()
{
IfConnectionIsActiveDo(TheComplicatedInteraction);
}
private void TheComplicatedInteraction()
{...}
private void IfConnectionIsActiveDo(Action action)
{
Status.Text = "Checking Connection";
checkConnection.BeginInvoke(EndConnectionIsActive,
new object[] { checkConnection, action });
}
private void EndConnectionIsActive(IAsyncResult ar)
{
var delegates = (object[]) ar.AsyncState;
var is_active_delegate = (Func<bool>) delegates[0];
var action = (Action) delegates[1];
bool is_active=is_active_delegate.EndInvoke(ar);
IsConnected = is_active;
Dispatcher.Invoke(DispatcherPriority.Normal,
new Action<bool>(UpdateStatusBarToReflectConnectionAttempt),is_active);
if (is_active) action();
}
我不是很滿意:它傳播的是曾經在兩個方法分爲五個(同步)代碼!這使得代碼非常混亂...
謝謝,我希望UI會神奇地響應Thread.Sleep期間的用戶操作,或者WPF的Application.DoEvents存在等價物。看來這是不好的解決方案 – Dabblernl 2009-09-13 18:36:38