2013-05-06 13 views
-1

我一直在試圖修改一些GUI元素之前/之後,我試圖同步和異步執行的TCP連接。嘗試修改另一個任務的GUI

public async void ConnectAsync(String h, String p, String n) 
{ 
    if (connected) 
     return; 

    try 
    { 
     hostname = new HostName(h); 
     port = p; 
     nickname = n; 

     await sock.ConnectAsync(hostname, port); 

     connected = true; 
     if (Connected != null) 
      Connected(this, EventArgs.Empty); 
    } 
    catch (Exception e) 
    { 
     sock.Dispose(); 
     hostname = null; 
     port = null; 
     nickname = null; 

     if (ConnectionFailed != null) 
      ConnectionFailed(this, EventArgs.Empty); 
    } 
} 

此方法以上由GUI類(下面的代碼)調用:

private void ConnectButtonClicked(object sender, RoutedEventArgs e) 
{ 
    string nickname; 

    if (Bar.Visibility == Windows.UI.Xaml.Visibility.Visible) 
     Bar.Visibility = Windows.UI.Xaml.Visibility.Collapsed; 

    if (Status.Visibility == Windows.UI.Xaml.Visibility.Collapsed) 
     Status.Visibility = Windows.UI.Xaml.Visibility.Visible; 

    qc.ConnectionFailed += new ConnectionFailedEventHandler(ConnectionFailedEventHandler); 
    qc.Connected += new ConnectedEventHandler(ConnectedEventHandler); 

    nickname = Nickname.Text; 

    /* HERE */ 
    Task.Run(() => qc.ConnectAsync("irc.quakenet.org", "6667", nickname)); 

    updateStatus("Connecting..."); 
    ConnectButton.IsEnabled = false; 
    Nickname.IsEnabled = false; 
    ProgLanguages.IsEnabled = false; 
} 

見,該方法提出了兩個不同的事件..

如果我調用此方法這樣的代碼與Task.Run(..)一起,引發這些事件,並在處理它們時,代碼嘗試通過此線程修改GUI並拋出異常。

如果我沒有Task.Run(..)調用方法,GUI凍結,我不能修改元素來顯示它是「連接」等等。

任何想法我怎麼能做到這一點?

+1

你有沒有試過在你的Task.Run前面等待,這樣它可以讓後臺任務完成(而不是阻止UI)。 YOu需要爲該底部方法簽名添加異步,並使其返回任務 – James 2013-05-06 22:48:16

+0

您遇到的異常是什麼?它是'跨線程操作無效'嗎? – PoweredByOrange 2013-05-06 22:51:34

+0

同意@James。你更好的設計將是等待ConnectAsync。並返回指示連接狀態的結果。無需事件。 – jure 2013-05-06 22:54:28

回答

2

首先,避免async void,所以請將ConnectAsync更改爲Task

然後,您的事件處理程序可以只做await qc.ConnectAsync(...),根本不需要Task.Run

+0

當然,它的工作!謝謝斯蒂芬。 – 2013-05-06 23:05:25

-1

您需要使用Control.Invoke()

我只是回答了同樣的問題在這裏:Background worker report string from a method

你需要用您用Control.Invoke調用調用任何UI控件()

規則是:任何UI控件都不能被用於創建它的另一個線程訪問。所以你需要「詢問」UI線程來執行更新你的UI控件的代碼。這是調用方法的工作(繼承自Control類)