简体   繁体   English

从静态线程函数访问控制元素

[英]Access control element from static thread function

I ve read lots of information about this stuff and i tried this: 我已经阅读了很多关于这些东西的信息,我试过这个:

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
  }
}

this: 这个:

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
  }
}

this: 这个:

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.

What do i do wrong? 我做错了什么? I thought that creating static control is an ultimate problem solve for this, but even this doesnt work... 我认为创建静态控件是解决此问题的最终问题,但即使这样也无法工作......

If I remember correctly in order to update the UI from another thread you need to use this invocation: 如果我没记错,为了从另一个线程更新UI,您需要使用此调用:

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

This will start MethodForUpdatingUI() from the UI thread, enabling you to access the controls. 这将从UI线程启动MethodForUpdatingUI() ,使您可以访问控件。

So, for use this in your code I'll try to change IncomingDataClass_SomeEvent : 所以,为了在你的代码中使用它,我将尝试更改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);
  }
}

Please feel free to correct me if this is not the case you are asking for or this is a bad pratice. 如果不是您要求的情况,请随时纠正我,否则这是一个不好的实践。 I've not tested the code. 我没有测试过代码。

You can only manipulate UI controls from UI thread. 您只能从UI线程操纵UI控件。 It doesn't matter if those controls are static or not, afaik. 如果那些控制是静态的,那么无关紧要。 Use Dispatcher object or SynchronizationContext object to modify controls from different thread. 使用Dispatcher对象或SynchronizationContext对象来修改来自不同线程的控件。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM