2013-04-30 33 views
2

我試圖用c#上的UI編寫服務器程序。 從後臺worker->分離線程調用服務器。在服務器'我必須更新關於什麼prot的cient連接以及一些其他參數的UI。 據我所知,我必須使用調用,我讀了它,但不知何故,我不能在我的代碼上實現它。因此,這裏是我的代碼,感謝提前任何幫助:無法更新服務器線程UI中的文本框

enter code here 


using System; 
using System.Collections.Generic; 
using System.ComponentModel; 
using System.Data; 
using System.Drawing; 
using System.Linq; 
using System.Text; 
using System.Windows.Forms; 
using System.Net; 
using System.Runtime.InteropServices; 
using System.Net.Sockets; 
using System.Threading; 
using System.IO; 
using System.Configuration; 
using System.Collections; 



namespace WindowsFormsApplication1 
{ 


    public partial class ServerAppMainDisplay : Form 
    { 
     public Int32 local_port = 40000; 
     public int StopOrSrart = 0; 
     public string localIP = "?"; 
     public string myHostName = "?"; 
     public string ServerIP = "Server IP: "; 
     public string DefaultPort = "Listening on default port: "; 
     public string MachineName = "Machine Name: "; 
     public static bool ThrdState = false; 
     public static bool TxtBoxVsblty = false; 

     public ServerAppMainDisplay() 
     { 
      InitializeComponent(); 
      textBox2.Text = DefaultPort; 
      textBox1.Text = ServerIP; 
      textBox3.Text = MachineName; 
      textUpdate.ShowDialogs(); 
     } 



     private void UpdateText(string text) 
     { 
      // Set the textbox text 
      textBox5.Text = text; 
     } 

     private void button1_Click(object sender, EventArgs e) 
     { 
      myHostName = Dns.GetHostName().ToString(); 
      localIP = Dns.Resolve(myHostName).AddressList[0].ToString(); 
      textBox1.Text = ServerIP + localIP; 
      textBox3.Text = MachineName + myHostName; 
      textBox2.Text = DefaultPort + local_port.ToString(); 
      backgroundWorker1.RunWorkerAsync(); 
     } 

     private void button2_Click(object sender, EventArgs e) 
     { 
      //Data Log txt 
     } 

     private void button3_Click(object sender, EventArgs e) 
     { 
      //Data Log Excel 
     } 

     private void button4_Click(object sender, EventArgs e) 
     { 
      DialogResult dialogResult = MessageBox.Show("Are you sure you want to stop server application?", 
       "Stop server application", MessageBoxButtons.YesNo); 
      if (dialogResult == DialogResult.Yes) 
      { 
       textBox2.Text = DefaultPort; 
       textBox1.Text = ServerIP; 
       textBox3.Text = MachineName; 
       myTCPServer.thread.Abort(); 
       myTCPServer.listener.Stop(); 
       myTCPServer.DefSoc.Dispose(); 
       for (int i = 1; i < 10; i++) 
       { 
        if (myTCPServer.Connection[i].portFlag) 
        { 
         myTCPServer.Connection[i].slistener.Stop(); 
         myTCPServer.Connection[i].socket.Dispose(); 
        } 
       } 
       ThrdState = true; 
       TxtBoxVsblty = false; 
      } 
      if (dialogResult == DialogResult.No) return; 
     } 

     private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e) 
     { 
      myTCPServer.myMain(); 
     } 

     private void button5_Click(object sender, EventArgs e) 
     { 
      DialogResult dialogResult = MessageBox.Show("Are you sure you want to exit server window application?", 
       "Exit server window application", MessageBoxButtons.YesNo); 
      if (dialogResult == DialogResult.Yes) 
      { 
       backgroundWorker1.Dispose(); 
       backgroundWorker1.CancelAsync(); 
       myTCPServer.thread.DisableComObjectEagerCleanup(); 
       myTCPServer.thread.Abort(); 
       this.Close(); 
       Application.Exit(); 
      } 
      if (dialogResult == DialogResult.No) return; 
     } 

    } 
    public class myTCPServer 
    { 
     public static Socket DefSoc; 
     public static Thread thread = new Thread(new ThreadStart(Service)); 
     public static TcpListener listener; 
     public struct Connection_s 
     { 
      public int port; 
      public bool portFlag; 
      public Socket socket; 
      public TcpListener slistener; 
     }; 
     public static myTCPServer.Connection_s[] Connection = new myTCPServer.Connection_s[10]; 
     public const int DefaultPort = 40000; 

     public static void myMain() 
     { 
      if (!WindowsFormsApplication1.ServerAppMainDisplay.ThrdState) 
       myTCPServer.thread.Start(); 
      else 
      { 
       myTCPServer.thread = new Thread(new ThreadStart(Service)); 
       myTCPServer.thread.Start(); 
      } 
     } 
     public static void Service() 
     { 

      for (int i = 1; i < 10; i++) 
      { 
       Connection[i].portFlag = false; 
       Connection[i].port = DefaultPort + i; 
      } 
      myTCPServer.listener = new TcpListener(DefaultPort); 
      myTCPServer.DefSoc = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); 
      while (true) 
      { 
       byte[] SndBfr; 
       string str; 
       myTCPServer.listener.Start(); 
       if (myTCPServer.listener.Pending()) 
       { 
        DefSoc = myTCPServer.listener.AcceptSocket(); 
       for (int i = 1; i < 10; i++) 
       { 

        if (Connection[i].portFlag == false) 
        { 
         Thread.Sleep(10); 
         str = "<" + Connection[i].port as string; 
         SndBfr = System.Text.Encoding.UTF8.GetBytes(str); 
         DefSoc.Send(SndBfr); 
         Thread.Sleep(10); 
         Connection[i].slistener = new TcpListener(Connection[i].port); 
         Connection[i].slistener.Start(); 
         Connection[i].socket = Connection[i].slistener.AcceptSocket(); 
         Connection[i].portFlag = true; 
         yourTextBox.Invoke(new UpdateTextCallback(this.UpdateText), 
          new object[]{」Text generated on non-UI thread.」}); 
         DefSoc.Disconnect(true); 
         DefSoc.Dispose(); 
         myTCPServer.listener.Stop(); 
         myTCPServer.listener = new TcpListener(DefaultPort); 
         myTCPServer.DefSoc = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); 
         break; 
        } 
        } 
       } 
       Thread.Sleep(10); 
       for (int i = 1; i < 10; i++) 
       { 
        if (Connection[i].portFlag == true) 
        { 
         int SndRslt = 0; 

         str = DateTime.Now.ToString(@"MM\/dd\/yyyy h\:mm tt"); 
         try 
         { 
          SndRslt = Connection[i].socket.Send(System.Text.Encoding.UTF8.GetBytes("+" + str)); 
         } 
         catch (SocketException) { } 
         if (SndRslt <= 0) 
         { 
          try 
          { 
           Connection[i].portFlag = false; 
           Connection[i].socket.Disconnect(true); 
           Connection[i].slistener.Stop(); 
          } 
          catch (SocketException) { } 
         } 
        } 
       } 
      } 
     } 
    } 
} 
+4

您已經提供了*方式*更多的代碼來展示問題,並且您沒有告訴我們當您嘗試發佈代碼時出了什麼問題。請閱讀http://tinyurl.com/so-list和http://tinyurl.com/so-hints – 2013-04-30 06:09:06

回答

3

更改UpdateText(string text)這樣:

private void UpdateText(string text) 
    { 
     if(textBox5.InvokeRequired) 
     { 
      Action a =() => UpdateText(text); 
      Invoke(a); 
     } 
     else 
      textBox5.Text = text; 
    } 

如果需要,這將調用文本框。

InvokeMSDN

,直到它 發現具有窗口句柄如果當前 控制的基礎窗口句柄還不存在控制或形式invoke方法向上搜索控件的父鏈。如果找不到合適的句柄 ,則Invoke方法將拋出 異常。在通話期間引發的例外情況將爲 傳播回主叫方。

+0

我該如何調用服務器線程的調用? – Alexander 2013-04-30 07:22:51

+0

是的。 'Invoke'將找到UI線程,並用它來更新文本框。請參閱編輯。 – 2013-04-30 07:26:22

+0

@Alexander是否有效? – 2013-04-30 11:48:41

0

你應該去「MethodInvoker」跨線程[此外,爲確保「辦法」執行的GUI線程]

也許這可以幫助:

MethodInvoker method = delegate{ 
     yourTextBox.Text = "the text you need"; 
    }; 
if (InvokeRequired) // You may skip this 
    BeginInvoke(method); 
0

調用一個委託到更新UI的功能和使用InvokeRequired在功能檢查,如果委託需要被調用。

例子:

Imports System.Management 



    Private watcher As New ManagementEventWatcher 
//delegate to udater UI function 
    Delegate Sub SetItemCallback(ByVal item As ListViewItem) 

    Private item1 As ListViewItem 

    Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load 

    Dim query As New WqlEventQuery("Win32_ProcessStartTrace") 
    watcher.Query = query 
    AddHandler watcher.EventArrived, AddressOf EventWorker 
    watcher.Start() 

    End Sub 

    'This method start when event arrived. It's invoked from another thead. (not UI thread) 

    Public Sub EventWorker(ByVal sender As Object, ByVal e As System.Management.EventArrivedEventArgs) 

    Try 

     Dim mbo As ManagementBaseObject = e.NewEvent 

     For Each p As PropertyData In mbo.Properties 

     item1 = New ListViewItem(p.Name) 

     If p.Value IsNot Nothing Then : item1.SubItems.Add(p.Value.ToString) 

     Else : item1.SubItems.Add(String.Empty) 

     End If 

     'updates de UI 

     Me.SetItem(item1) 


     Next 

    Catch ex As Exception 

     Console.WriteLine(ex.Message) 

    End Try 

    End Sub 

    'If InvokeRequired (no UI thread) create the delegate and invoke it else update the UI 
    Private Sub SetItem(ByVal itm As ListViewItem) 

    If Me.ListView1.InvokeRequired Then 

     Dim d As New SetItemCallback(AddressOf SetItem) 

     Me.Invoke(d, New Object() {itm}) 

    Else 

     ListView1.Items.Add(itm) 

    End If 

    End Sub 

    Private Sub Form1_FormClosed(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosedEventArgs) Handles Me.FormClosed 

    watcher.Stop() 

    End Sub