非静态字段方法需要对象引用或 property/field 初始化程序不能引用非静态字段方法或 属性

An object reference is required for the non-static field method or property/field initializer cannot reference the non-static field method or property

我正在制作一个程序,我偶然发现了这个二合一的问题,第一个问题导致了另一个问题。我还没有发现有人有两个问题导致彼此的问题。我还在学习,从我遇到的其他问题中学到了很多,但我找不到解决这个问题的方法。

它与线程有关。我想制作一个线程,它可以每秒左右在富文本框中放置一些内容,同时我仍然可以按下按钮来启动和停止它。但是要创建线程可以 运行 的函数,我需要将函数设为静态。否则我会收到错误 "A field initializer cannot reference the non-static field, method, or property"。但是当一个函数是静态的时,它不能访问任何创建的项目,比如 richTextBox1。因为如果我尝试更改它的文本,我会收到错误 "Error 1 An object reference is required for the non-static field, method, or property"。如果我通过删除静态来解决这个问题,线程将无法工作。

我做了一个比完整的小的演示程序,但有同样的问题。 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();
            }
        }
    }
}

要使用此代码,只需创建一个表单应用程序、添加两个按钮和一个富文本框,它应该可以工作。

提前感谢您的回答。

But to make a function that a thread can run, I need to make the function static.

摆脱 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
        }
    }

但是忽略上面的"fix"因为不推荐使用Suspend()/Resume()

参见Pausing and Resuming Threads

Important

Starting with the .NET Framework version 2.0, the Thread.Suspend and Thread.Resume methods are marked obsolete and will be removed in a future release.

The Thread.Suspend and Thread.Resume methods are not generally useful for applications and should not be confused with synchronization mechanisms. Because Thread.Suspend and Thread.Resume do not rely on the cooperation of the thread being controlled, they are highly intrusive and can result in serious application problems like deadlocks (for example, if you suspend a thread that holds a resource that another thread will need).

能够pause/resume你的循环的一种方法是使用这样的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
    }

}