0

私はこのことについて多くの情報を読みました、そして私はこれを試しました:

class Server
{
... 
  public Server(int Port, ListBox ex_lb, PictureBox ex_pb)
  {
    ServerWork = new Thread(() => ServerFunction(Listener, ex_lb, ex_pb));
    ServerWork.Start();
  }
  static void ServerFunction(TcpListener ex_listener, ListBox ex_lb, PictureBox ex_pb)
  {
    //and any access to ex_lb throws exception, didnt debug to access to ex_pb
  }
}

これ:

private static IncomingDataClass g_IDC = new IncomingDataClass();

private class IncomingDataClass
{
  static string data = "";
  public string Data
  {
    get { return data; }
    set { 
      data = value;
      SomeEvent(this,null,data);
    }
  }            
}

void IncomingDataClass_SomeEvent(object sender, EventArgs e, string ex_data)
{
  if (ex_data.Contains("listbox"))
  {
    ex_data = ex_data.Remove(ex_data.IndexOf("listbox"), "listbox".Length);
    listBox1.Items.Add(ex_data);
  }
}

delegate void MyEventHandler(object sender, EventArgs e, string ex_data);
static event MyEventHandler SomeEvent;
// in form load event
SomeEvent += IncomingDataClass_SomeEvent;
class Server
{
... 
  public Server(int Port, ListBox ex_lb, PictureBox ex_pb)
  {
    ServerWork = new Thread(() => ServerFunction(Listener));
    ServerWork.Start();
  }
  static void ServerFunction(TcpListener ex_listener)
  {
    //and any change of g_IDC.Data throws exception here
  }
}

これ:

private static ListBox listBox1 = new ListBox();

private void Form1_Load(object sender, EventArgs e)
{
  ...
  listBox1.FormattingEnabled = true;
  listBox1.Location = new System.Drawing.Point(12, 256);
  listBox1.Name = "listBox1";
  listBox1.Size = new System.Drawing.Size(258, 108);
  listBox1.TabIndex = 6;
  Controls.Add(listBox1);
}
//anyways, even if i create new ListBox lb = listBox1 in ServerFunction(..), it throws System.InvalidOperationException => Access attempt to listBox1 not from thread where is was created.

私は何を間違っていますか?静的制御を作成することがこれに対する究極の問題解決であると考えましたが、これでもうまくいきません...

4

2 に答える 2

2

私の記憶が正しければ、別のスレッドから UI を更新するには、次の呼び出しを使用する必要があります。

this.Invoke((MethodInvoker)delegate
    {
        MethodForUpdatingUI();
    });

これはMethodForUpdatingUI()UI スレッドから開始され、コントロールにアクセスできるようになります。

だから、あなたのコードでこれを使用するために、私は変更しようとしますIncomingDataClass_SomeEvent:

void IncomingDataClass_SomeEvent(object sender, EventArgs e, string ex_data)
{
        this.Invoke((MethodInvoker)delegate
        {
            UpdateListBox(ex_data);
        });
}

UpdateListBox(string ex_data)
{
  if (ex_data.Contains("listbox"))
  {
    ex_data = ex_data.Remove(ex_data.IndexOf("listbox"), "listbox".Length);
    listBox1.Items.Add(ex_data);
  }
}

これがあなたが求めているケースではない場合、またはこれが悪い習慣である場合は、お気軽に修正してください. 私はコードをテストしていません。

于 2013-04-15T10:10:17.797 に答える
0

UI スレッドからのみ UI コントロールを操作できます。これらのコントロールが静的かどうかは問題ではありません。Dispatcher オブジェクトまたは SynchronizationContext オブジェクトを使用して、別のスレッドからコントロールを変更します。

于 2013-04-15T10:28:29.303 に答える