Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 从线程调用可以工作,但可以';做起来不简单吗?_C#_Multithreading_Forms - Fatal编程技术网

C# 从线程调用可以工作,但可以';做起来不简单吗?

C# 从线程调用可以工作,但可以';做起来不简单吗?,c#,multithreading,forms,C#,Multithreading,Forms,我设法制作了一个简单的程序,从不同的线程和类更新文本框。以视觉方式学习线程的最简单方法。;) 代码由msdn提供的文档编制而成。它运行,我看不到内存泄漏。但我觉得这可以做得更简单 主要有两类;表单和背景类。后台类中有一个名为generateStream的函数,该函数通过对名为updateTextBox的函数的委托来更新Form类中的文本框 按下按钮开始时,将执行两个操作。直接调用First generateStream。当generateStream就绪时,将生成一个线程,该线程将再次运行gen

我设法制作了一个简单的程序,从不同的线程和类更新文本框。以视觉方式学习线程的最简单方法。;)

代码由msdn提供的文档编制而成。它运行,我看不到内存泄漏。但我觉得这可以做得更简单

主要有两类;表单和背景类。后台类中有一个名为generateStream的函数,该函数通过对名为updateTextBox的函数的委托来更新Form类中的文本框

按下按钮开始时,将执行两个操作。直接调用First generateStream。当generateStream就绪时,将生成一个线程,该线程将再次运行generateStream(通过函数)。当使用不同的线程时,TextBox需要调用解决方案

所有这些都得到了实施并发挥了作用。我认为这是相当多的代码,也许可以做得更干净

main类中更新表单并被回调的函数

public void updateTextBox(string strtext)
    {
        if (this.InvokeRequired) //When calling from another thread; invoke is required.
        {
            SetTextCallBack cb = new SetTextCallBack(updateTextBox);
            this.Invoke(cb, new object[] { strtext });

        }
        else //Call can be performed safely.
        {
            textBoxStatus.SelectionStart = textBoxStatus.Text.Length;
            textBoxStatus.AppendText(strtext);
            textBoxStatus.Update();
        }
    }
通过单击按钮完成的操作

    private void buttonStart_Click(object sender, EventArgs e)
    {
        buttonStart.Enabled = false;

        /*
         * Step 1: Let's call the function blocking.
         *          The GUI will not respond to mouse geastures. Hoover mouse over inputbox to see no change in pointer.
         */
        bg.generateStream(numberOfCalls, "GUI Thread: ");


        /*
         * Step 2: Let's call the function in a seperate thread.
         *          The GUI will now respond to the mouse. Hoover mouse over inputbox to see pointer change.
         */
        Thread sepThread = new Thread(new ThreadStart(this.TheFunction));
        sepThread.Start();

        buttonStart.Enabled = true;
    }
后台类中的generateStream函数

    public void generateStream(int amountOfStreams, string inpString)
    {
        for (int i = 0; i < amountOfStreams; i++)
        {
            Thread.Sleep(1000); //Easy does it.
            myCallBack(inpString + i.ToString() + System.Environment.NewLine); //This is the text to the Main Form.
        }
    }
public void generateStream(int-amountOfStreams,string-inpString)
{
对于(int i=0;i

使用线程时,我现在使用两个回调来更新文本框。一个是从后台类到表单,另一个是实现调用。例如,是否没有信号量解决方案可以使我的updateTextBox函数只能有一个线程访问?

当InvokeRequest为true时调用Invoke没有什么害处。我还喜欢在C#2.0中使用匿名方法。您可以按如下方式简化功能:

private delegate void SimpleProc();
private void updateTextBox(string strtext) {
    this.Invoke(new SimpleProc(delegate() {
        textBox1.SelectionStart = textBox1.Text.Length;
        textBox1.AppendText(strtext);
        textBox1.Update(); // only needed if updateTextBox is called from UI thread
    }), null);
}
将Invoke替换为BeginInvoke对于fire-and-forget场景非常有用,在这种场景中,您不希望后台线程等待UI线程完成更新,但您需要确定这是否适合您的应用程序


更新后的函数可以直接从UI线程或后台线程调用。不需要回调;使用的唯一回调函数是updateTextBox中的匿名函数。没有比这更简单的了。事实上,这很简单,在很多情况下不需要创建单独的函数来调用UI线程。

我不太明白你的问题是什么,你能试着改写你的最后一段来更好地解释你的问题是什么吗。你是对的,它太多文本,没有方向。作为提示,你的主要问题
我认为这是相当多的代码,也许可以做得更干净。
应该放在文章的底部而不是中间,这样也可以很容易找到。我强烈推荐文章“”。您的最后一个问题是,例如,是否没有信号量解决方案可以使我的updateTextBox函数只能有一个线程访问权限?
与此相反。我在上一篇评论中强调的那句话是“目标不是步骤”的完美例子,谢谢!这已经省去了if语句的需要,并且使它变得更简单。我所付出的唯一代价就是总是执行额外的回调。我在想信号灯之类的东西。但直到现在,我才发现调用是处理这个问题的正确方法。实际上,如果您从UI线程进行调用,Invoke基本上会执行原始代码所做的操作,即直接调用回调,而不向消息队列发送任何消息。在这种情况下,性能影响可以忽略不计;调用只涉及一些额外的函数调用和隐藏的代码。我猜回调中实际更新UI的代码需要花费更多的时间。如果从工作线程调用Invoke,则会将自定义窗口消息发布到消息队列,以便在将来某个时候由UI线程处理。