我正在制作一个程序,我偶然发现了这个二合一问题,第一个问题导致了另一个问题。我还没有找到一个问题,哪个人有两个问题导致彼此。我还在学习,并从我遇到的其他问题中学到了很多东西,但我无法找到解决这个问题的方法。
它与线程有关。我想创建一个线程,它可以每隔一秒左右在富文本框中放置一些东西,而我仍然可以按下按钮来启动和停止它。但是要创建一个线程可以运行的函数,我需要使函数静态。否则我将收到错误"字段初始化程序无法引用非静态字段,方法或属性"。但是当一个函数是静态的时,它不能访问任何创建的项,比如richTextBox1。因为如果我尝试更改它的文本,我会收到错误"错误1非静态字段,方法或属性需要对象引用"。如果我通过删除静态来解决这个问题,那么线程将无法工作。
我做了一个小于完整程序的演示程序,但是遇到了同样的问题。 Button1是启动线程的按钮,Button2是停止它的按钮。
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Threading;
namespace threading_non_static_problem_demo
{
public partial class Form1 : Form
{
static Thread thr = new Thread(new ThreadStart(demofunc));
int checkthr = 0; //int to check if the thread has been running before (I like to do things like this)
int ifthrrun = 0; //int to check if the thread is running
public Form1()
{
InitializeComponent();
button2.Enabled = false; // so you can't click the "stop" button if nothing is running
}
private void richTextBox1_TextChanged(object sender, EventArgs e)
{
}
static void demofunc()
{
while (true)
{
Thread.Sleep(1000);
richTextBox1.Text = richTextBox1.Text + "text added"; // <-- here's the problem
MessageBox.Show("tried to add text"); // you can use this messagebox to check if the thread is working correctly
}
}
private void button1_Click(object sender, EventArgs e)
{
if (checkthr == 0) // check if the thread has run before, 0 is no, 1 is yes, and then start or resume it
{
thr.Start();
ifthrrun = 1;
button2.Enabled = true;
button1.Enabled = false;
}
else if (checkthr == 1)
{
thr.Resume();
ifthrrun = 1;
button2.Enabled = true;
button1.Enabled = false;
}
}
private void button2_Click(object sender, EventArgs e)
{
thr.Suspend();
checkthr = 1;
ifthrrun = 0;
button2.Enabled = false;
button1.Enabled = true;
}
protected override void OnFormClosing(FormClosingEventArgs e) // if the program is closing, check the thread's state and act accordingly
{
if (ifthrrun == 0)
{
if (checkthr == 1)
{
thr.Resume();
thr.Abort();
}
else if (checkthr == 0)
{
}
}
else if (ifthrrun == 1)
{
thr.Abort();
}
}
}
}
要使用此代码只需创建表单应用程序,添加两个按钮和一个富文本框,它应该可以正常工作。
提前感谢您的答案。
答案 0 :(得分:0)
但是要创建一个线程可以运行的函数,我需要制作一个 功能静态。
删除static
声明并将“thr”变量的初始化移动到构造函数中,如下所示:
Thread thr;
public Form1()
{
InitializeComponent();
button2.Enabled = false; // so you can't click the "stop" button if nothing is running
thr = new Thread(new ThreadStart(demofunc));
Control.CheckForIllegalCrossThreadCalls = false;
}
private void demofunc()
{
while (true)
{
Thread.Sleep(1000);
richTextBox1.Text = richTextBox1.Text + "text added"; // <-- problem "solved" by disabling Control.CheckForIllegalCrossThreadCalls
}
}
但忽略上述“修复”,因为不推荐使用Suspend()/ Resume()。
请参阅Pausing and Resuming Threads:
重要
从.NET Framework 2.0版开始,Thread.Suspend和 Thread.Resume方法已标记为已过时,将在a中删除 未来发布。
Thread.Suspend和Thread.Resume方法不是 通常对应用程序有用,不应混淆 同步机制。因为Thread.Suspend和Thread.Resume 他们不依赖于受控线程的合作 是高度侵入性的,可能导致严重的应用程序问题 像死锁一样(例如,如果你挂起一个持有a的线程) 另一个线程需要的资源)。
能够暂停/恢复循环的一种方法是使用这样的ManualResetEvent:
Thread thr;
ManualResetEvent mre = new ManualResetEvent(false);
public Form1()
{
InitializeComponent();
button2.Enabled = false; // so you can't click the "stop" button if nothing is running
thr = new Thread(new ThreadStart(demofunc));
}
private void demofunc()
{
while (!this.IsDisposed && !this.Disposing)
{
Thread.Sleep(1000);
if (!this.IsDisposed && !this.Disposing)
{
this.Invoke((MethodInvoker)delegate {
richTextBox1.AppendText("text added");
});
}
mre.WaitOne();
}
}
private void button1_Click(object sender, EventArgs e)
{
button1.Enabled = false;
mre.Set();
if (!thr.IsAlive)
{
thr.Start();
}
button2.Enabled = true;
}
private void button2_Click(object sender, EventArgs e)
{
button2.Enabled = false;
mre.Reset();
button1.Enabled = true;
}
protected override void OnFormClosing(FormClosingEventArgs e) // if the program is closing, check the thread's state and act accordingly
{
mre.Set(); // make sure the loop continues so it can drop out
}
}