NullReferenceException @ Dispatcher&其他GUI问题

时间:2014-12-10 21:43:33

标签: c# multithreading user-interface

我一直在尝试实现多类线程GUI管理。因为我希望不同的线程分布在不同的.cs文件中的多个类中,以根据需要更新UI。

我搜索了stackoverflow和其他来源,发现大多数人都使用Dispatcher.Invoke或类似的东西。所以我决定开始测试......

下面是一个名为wThread.cs的类中的线程,

public class wThread
{
    public EventHandler SignalLabelUpdate;
    public Dispatcher uiUpdate;

    public wThread()
    {
        uiUpdate = Program.myForm.dispat;
        //the uiUpdate seems to be null for some reason... If i am doing it wrong how do i get the dispatcher?
        Thread myThread = new Thread(run);
        myThread.Start();
    }
    Action myDelegate = new Action(updateLabel);
    // is there a way i can pass a string into the above so updatelabel will work? 

    public void updateLabel(String text)
    {
        if (SignalLabelUpdate != null)
            SignalLabelUpdate(this, new TextChangedEvent(text));
    }

    public void run()
    {
        while (uiUpdate == null)
            Thread.Sleep(500);
        for (int i = 0; i < 1000; i++)
        {
            //I hope that the line below would work 
            uiUpdate.BeginInvoke(new Action(delegate() { Program.myForm.label1.Text = "count at " + i; }));
            // was also hoping i can do the below commented code
            // uiUpdate.Invoke(myDelegate)
            Thread.Sleep(1000);
        }
    }
}

下面是我的form1.cs,它是visual studio 2012预装的代码,

public partial class Form1 : Form
{
    public Dispatcher dispat;
    public Form1()
    {
        dispat = Dispatcher.CurrentDispatcher;
        InitializeComponent();
        wThread worker = new wThread();
    }
}

我的大多数问题都在上面的评论中,但是这些是列出的:

  1. uiUpdate由于某种原因似乎是空的...如果我做错了我怎么得到调度员? (wThread.cs问题)

    uiUpdate = Program.myForm.dispat'
    
  2. 有没有办法可以将字符串传递到上面,所以updatelabel会有效吗?

    Action myDelegate = new Action(updateLabel);
    
  3. 我希望下面这行能够正常工作

    uiUpdate.BeginInvoke(new Action(delegate() { Program.myForm.label1.Text = "count at " + i; }));
    
  4. 也希望我能做以下评论代码

    uiUpdate.Invoke(myDelegate)
    
  5. 编辑:我将wThread构造函数wThread worker = new wThread()移出了form1初始化区域......并修复了我的nullpointer。相反,我将wThread构造函数移动到构造表单的静态主void中...就像Application.Run(myForm);

    不幸的是,在我关闭UI之前,wThread不会启动。对此最好的做法是什么?在Application.Run启动我的Form并使用该线程启动我的真实线程之前创建另一个线程?

1 个答案:

答案 0 :(得分:0)

@ 1:在Form1构造函数中,在dispat = Dispatcher.CurrentDispatcher;放置一个断点并检查值是多少。可能只是Dispatcher.CurrentDispatcher为空而你必须得到它,即稍晚,而不是在ctor

@ 2是的。使用Func<string>代替操作。 InvokeBeginInvoke接受委托,还有一组params object[]形成委托调用的参数。当然,传递的参数数组必须与委托签名完全匹配,因此当使用Func<string>时,只使用一个对象[]:字符串。

@ 3 - 是的,只要i是一个可以被委托闭包捕获的简单局部变量,那就行了。如果它是foreach迭代器或某个非本地成员,它可能会有问题,但是,不同的故事。

@ 4 - 是的,它会起作用,只记得传递Func<string>的参数。