从其他线程访问对象

时间:2015-04-05 23:28:04

标签: c# multithreading delegates

我试图能够从其他主题访问主表单中的某些控件。

让我们考虑一下这张照片:

enter image description here

我想将该控件(在我的情况下是一个面板)实例化到第二个线程中。

我的问题是我找到了很多答案,只是修改一个控件(例如设置一个文本框的文本)而不能读取/写入它的属性,就像它一样。宾语。 (代表和东西)

我当前的代码:(因为我已经在另一个帖子中创建了面板而无法正常工作)

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#?"并没有真正回答我的问题,因为我想阅读对象属性,而不仅仅是写。虽然这是一个非常有趣的主题。

2 个答案:

答案 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关键字禁用此功能。

查看MSDN Reference

修改

您可以在Form1.Designer.cs文件中进行更改。 E.g:

private volatile System.Windows.Forms.Button button1;