我试图能够从其他主题访问主表单中的某些控件。
让我们考虑一下这张照片:
我想将该控件(在我的情况下是一个面板)实例化到第二个线程中。
我的问题是我找到了很多答案,只是修改一个控件(例如设置一个文本框的文本)而不能读取/写入它的属性,就像它一样。宾语。 (代表和东西)
我当前的代码:(因为我已经在另一个帖子中创建了面板而无法正常工作)
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:主题" How to update the GUI from another thread in C#?"并没有真正回答我的问题,因为我想阅读对象属性,而不仅仅是写。虽然这是一个非常有趣的主题。
答案 0 :(得分:1)
<强> EDITED 强>
您不希望将控件“实例化”到另一个线程中。
如果您使用的是Winforms(Win32)与WPF(Windows Presentation Foundation),则存在一些差异。 Win32 UI库(“Winforms”)不是线程安全的。如果你允许除主UI线程之外的任何线程直接摆弄控件,你将得到不可预测的结果,内存泄漏和彻底崩溃。
另一方面,WPF UI库 是线程安全的,但是仍然有很多问题需要注意,我不是要在这个短片中解决它们(我希望)回答。 ; - )
您甚至不希望跨线程边界访问控件实例的引用。你想要做的是通知UI线程做你想做的事情。皮猫的方法不止一种,你需要做一些研究。但基本思想是你从另一个线程设置某种共享状态,告诉UI线程采取行动,或者引发在UI线程上执行的事件,然后从该事件处理程序启动与控件的交互。查找消息泵等概念。但是你几乎肯定不想做的是摆弄Windows消息循环以“子类化”表单和控件。
其他有用的工具包括BackgroundWorker类和较新的Tasks库。你应该选择和使用其中一个,但不能同时使用。一般模型是你将从你的UI线程启动一个任务线程,当它返回时,它将在UI线程中引发一个事件,你可以从那里使用表单上的控件进行有用的工作。
答案 1 :(得分:-2)
通常c#优化变量只能由一个线程访问。
您可以使用volatile
关键字禁用此功能。
修改强>
您可以在Form1.Designer.cs
文件中进行更改。 E.g:
private volatile System.Windows.Forms.Button button1;