我正在尝试使用线程并防止程序在线程忙时冻结。它应该显示进度(写入 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();
}
}
}
编辑:
顺便说一句,对于任何想知道的人,我是多线程的新手,我只是想编写一个小程序来了解执行此操作的最佳方法。
我知道我之前的调用并没有真正帮助,因为我仍然没有给表单更新的机会,所以它到了那里。
好的,所以像这样运行 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);
}));
}
}
(如果我在这方面完全错了,我不介意阅读一些示例/线程,除了后台工作人员之外,我仍在尝试查看执行此操作的最佳方法)
编辑2:
我通过减少写入量来减少调用次数,但增加延迟会产生与持续写入相同的效果,只是减少负载。
private void writeText(TextBox textBox, string text)
{
for (int i = 0; i < 500; i++)
{
Invoke(new MethodInvoker(() =>
{
textBox.Text += text;
Thread.Sleep(2);
}));
}
}
编辑 3:
Sumeet 的示例使用
应用程序.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();
}
}