【问题标题】:Access object from other thread [duplicate]从其他线程访问对象[重复]
【发布时间】:2015-04-05 23:28:04
【问题描述】:

我正在尝试从另一个线程访问我的主窗体中的一些控件。

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

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

我的问题是我找到了很多答案,这些答案只是修改了一个控件(例如设置文本框的文本)并且无法像对象一样读取/写入它的属性。 (代表和东西)

我当前的代码:(不工作,因为我在另一个线程中创建了面板)

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

【问题讨论】:

  • "线程'如何从 C# 中的另一个线程更新 GUI?'并没有真正回答我的问题,因为我想读取对象属性,而不仅仅是写入" - 您仍然可以使用线程编组技术来读取属性。但是,我认为您应该重新设计您的应用程序,因为线程编组非常昂贵以至于它可能成为首先使用线程的重大障碍
  • 嗯..我不知道如何重新设计它..基本上我正在制作一个关卡编辑器,我想制作一个画布和一个“控件”部分 (i.stack.imgur.com/iIN8X.png) .主题是更新和绘制画布。我会在游戏开发上找到一些建议。无论如何,谢谢。
  • @Riptide Reading 属性不会有什么大不了的。您只需要编组这些调用并从 UI 线程中进行实际读取,或多或少与您进行写入的方式相同。

标签: c# multithreading delegates


【解决方案1】:

已编辑

您不想将控件“实例化”到另一个线程中。

如果您使用的是 Winforms (Win32) 与 WPF(Windows Presentation Foundation),则存在一些差异。 Win32 UI 库(“Winforms”)不是线程安全的。如果您允许主 UI 线程以外的任何线程直接摆弄控件,您将获得不可预知的结果、内存泄漏和彻底崩溃。

另一方面,WPF UI 库线程安全的,但仍有很多问题需要注意,我并不想在这短短的时间内解决所有问题(我希望)回答。 ;-)

您甚至不希望跨线程边界访问对控件实例的引用。您想要做的是向 UI 线程发出信号以执行您想要的操作。给猫剥皮的方法不止一种,你需要做一些研究。但基本思想是,您从另一个线程设置某种共享状态,告诉 UI 线程采取行动,或引发在 UI 线程上执行的事件,然后从该事件处理程序启动与控件的交互。查找诸如消息泵之类的概念。但是你几乎绝对不想做的是摆弄 Windows 消息循环来“子类化”表单和控件。

其他有用的工具包括BackgroundWorker 类和更新的Tasks 库。您应该选择并使用其中之一,但不能同时使用两者。一般模型是,您将从您的 UI 线程启动一个任务线程,当它返回时,它将在 UI 线程中引发一个事件,您可以在其中对表单上的控件进行有用的工作。

【讨论】:

  • 谢谢,我将阅读任务库。我的意思是指,而不是实例化,你是对的。
  • “您希望从另一个线程访问对控件的引用” - 这是不正确的。工作线程通过 消息泵 将其请求编组到 UI 线程,该 UI 线程执行请求以操作控件。工作的是 UI 线程而不是工作线程。认为工作线程有“对控件的引用”是不正确的
  • “Win32 不是线程安全的,句号” - 你的意思是 Win32 windows 还是 GDI-related 函数,因为 Win32 相当广泛,其中很大一部分是线程安全的。您认为重叠或 IOCP 是如何运作的?
  • @MickyDuncan 我显然只指 Win32 API(“Winforms”)的 UI 部分。海报询问有关 Windows 窗体上的控件。 ;-)
  • 谢谢克雷格,也许只是稍微修改一下这句话,一切都很好。 :)
猜你喜欢
  • 2012-12-27
  • 2012-07-22
  • 1970-01-01
  • 2018-09-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多