Ran*_*Guy 6 c# multithreading invoke
我正在尝试使用线程并防止程序在线程繁忙时冻结.它应该显示进度(写入0/1)并且不仅仅是在完成后显示结果,同时冻结表格.
在当前程序中,我正在尝试写入文本框,实际上看到不断进展,并且表单不会受到其他线程任务的影响.
我现在拥有的是我可以使用调用写入带有线程的文本框,但它只显示结果(表单在线程繁忙时冻结),并且表单冻结.
表格图片:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;
namespace MultiThreading
{
public partial class MultiThreading : Form
{
public MultiThreading()
{
InitializeComponent();
}
Thread writeOne, writeTwo;
private void writeText(TextBox textBox, string text)
{
if (textBox.InvokeRequired)
{
textBox.BeginInvoke((MethodInvoker)delegate()
{
for (int i = 0; i < 500; i++)
{
textBox.Text += text;
}
});
}
else
{
for (int i = 0; i < 500; i++)
{
textBox.Text += text;
}
}
}
private void btnWrite1_Click(object sender, EventArgs e)
{
writeOne = new Thread(() => writeText(txtOutput1, "0"));
writeOne.Start();
}
private void btnWrite2_Click(object sender, EventArgs e)
{
writeTwo = new Thread(() => writeText(txtOutput2, "1"));
writeTwo.Start();
}
private void btnClear1_Click(object sender, EventArgs e)
{
txtOutput1.Clear();
}
private void btnClear2_Click(object sender, EventArgs e)
{
txtOutput2.Clear();
}
private void btnWriteBoth_Click(object sender, EventArgs e)
{
writeOne = new Thread(() => writeText(txtOutput1, "0"));
writeTwo = new Thread(() => writeText(txtOutput2, "1"));
writeOne.Start();
writeTwo.Start();
}
private void btnClearBoth_Click(object sender, EventArgs e)
{
txtOutput1.Clear();
txtOutput2.Clear();
}
}
}
Run Code Online (Sandbox Code Playgroud)
编辑:
顺便说一句,对于任何想知道的人,我都是多线程的新手,我只是想写一个小程序来了解最好的方法.
我知道我以前的调用并没有真正帮助,因为我仍然没有给表单提供更新的机会,所以它到达那里.
好的,这样运行1个这样的线程,但仍然在一起运行多个线程,直到线程完成后才会更新表单.
我添加了一个thread.sleep(),所以我可以在写作时尝试清除,看看我是否仍然可以使用该表单.
写入1个文本框时,我仍然可以在写入时清除屏幕.
但是一旦我使用2个线程,我就不能再使用该表单直到线程完成,并给出输出.
private void writeText(TextBox textBox, string text)
{
for (int i = 0; i < 500; i++)
{
Invoke(new MethodInvoker(() =>
{
textBox.Text += text;
Thread.Sleep(2);
}));
}
}
Run Code Online (Sandbox Code Playgroud)
(如果我完全错了关于这个我不介意通过一些例子/线程读取,我还在想看看是做到这一点的最好办法,除了一个BackgroundWorker)
编辑2:
我通过减少写入量来减少调用次数,但是增加延迟会产生相同的持续写入效果,只是减少负载.
private void writeText(TextBox textBox, string text)
{
for (int i = 0; i < 500; i++)
{
Invoke(new MethodInvoker(() =>
{
textBox.Text += text;
Thread.Sleep(2);
}));
}
}
Run Code Online (Sandbox Code Playgroud)
编辑3:
Sumeet的例子可以使用
Application.DoEvents();
(注意s,.DoEvent不起作用,可能是错字:P),同时写多个字符串并让它们显示进度而不仅仅是结果.
所以代码再次更新:)
*使用新按钮创建5个线程,将随机数写入两个文本框
private void writeText(TextBox textBox, string text)
{
for (int i = 0; i < 57; i++)
{
Invoke(new MethodInvoker(() =>
{
textBox.Text += text;
Thread.Sleep(5);
Application.DoEvents();
}));
}
}
private void btnNewThread_Click(object sender, EventArgs e)
{
Random random = new Random();
int[] randomNumber = new int[5];
for (int i = 0; i < 5; i++)
{
randomNumber[i] = random.Next(2, 9);
new Thread(() => writeText(txtOutput1, randomNumber[i-1].ToString())).Start();
new Thread(() => writeText(txtOutput2, randomNumber[i-1].ToString())).Start();
}
}
Run Code Online (Sandbox Code Playgroud)
小智 7
此解决方案有效!检查过了.
问题是你一直告诉UI线程改变文本,但永远不要让它有时间向你显示更新的文本.要使UI显示已更改的文本,请添加Application.DoEvents行,如下所示:
textBox.Text += text;
Application.DoEvents();
Run Code Online (Sandbox Code Playgroud)
ps:删除你的If/Else循环的else块,它是多余的,并且如其他人所指出的那样,没有任何使用创建这两个线程,因为它们正在做的就是在UI线程本身上发布消息.
您仍在执行单线程任务,只需在UI线程上重新启动它即可.
for (int i = 0; i < 500; i++){
string text = ""+i;
textBox.BeginInvoke((MethodInvoker)delegate()
{
textBox.Text += text;
});
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
23405 次 |
最近记录: |