问题
I'm trying to be able to access some controls in my main form from an other thread.
Let's consider this picture:

I want to Instantiate that control (It's a panel in my case) into the second thread.
My problem is that i have found a LOT of answers that just modifies a control (Set the text of a textbox for instance) and not be able to read/write it's properties like it's an object. (Delegates and stuff)
My current code: (Not working because i've created the panel in the other thread)
public partial class Main : Form
{
Graphics g;
Thread drawCanvasThread;
int pos = 0;
public Main()
{
InitializeComponent();
}
private void Main_Load(object sender, EventArgs e)
{
g = canvas.CreateGraphics();
drawCanvasThread = new Thread(() => HandleCanvas(canvas));
drawCanvasThread.Start();
}
private void HandleCanvas(Panel objCanvas)
{
Panel canvas = objCanvas;
Point mousePos;
while(true)
{
mousePos = canvas.PointToClient(Cursor.Position);
//UPDATE CANVAS
//DRAW CANVAS
Thread.Sleep(17); //1000 / 17 ~~= 60
}
}
private void Main_FormClosing(object sender, FormClosingEventArgs e)
{
drawCanvasThread.Abort();
}
}
PS: The thread "How to update the GUI from another thread in C#?" doesn't really answers my question, because i want to read the object properties, and not only write. Though it's a very interesting thread.
回答1:
EDITED
You don't want to "instantiate" the control into the other thread.
There are some differences if you're working with Winforms (Win32) vs WPF (Windows Presentation Foundation). The Win32 UI libraries ("Winforms") are not thread-safe. You'll get unpredictable results, memory leaks and outright crashes if you allow any thread other than the main UI thread to directly fiddle with controls.
The WPF UI library is thread-safe, on the other hand, but there are still plenty of issues to be aware of and I'm not trying to address them all in this short (I hope) answer. ;-)
You really don't even want access across a thread boundary to a reference to a control instance. What you want to do is signal the UI thread to do what you want. There's more than one way to skin that cat, and you'll want to do some research. But the basic idea is that you set some kind of shared state from the other thread that tells the UI thread to take action, or raise an event that executes on the UI thread, and you initiate your interaction with the control from that event handler. Look up concepts like a message pump. But what you almost definitely don't want to do is fiddle with the Windows message loop to "subclass" the forms and controls.
Other useful tools include the BackgroundWorker class, and the newer Tasks library. You should pick and use one or the other, but not both simultaneously. The general model is that you'll launch a task thread from your UI thread, and when it returns it will raise an event in the UI thread from where you can do useful work with the controls on your forms.
回答2:
Normally c# optimizes variables for only be accessed by one thread.
You can disable this with the volatile
Keyword.
Check out the MSDN Reference.
EDIT:
You can change it in the Form1.Designer.cs
file. E.g.:
private volatile System.Windows.Forms.Button button1;
来源:https://stackoverflow.com/questions/29463393/access-object-from-other-thread