【问题标题】:An object reference is required for the non-static field method or property/field initializer cannot reference the non-static field method or property非静态字段方法需要对象引用,或者属性/字段初始化程序无法引用非静态字段方法或属性
【发布时间】:2015-08-04 20:08:43
【问题描述】:

我正在编写一个程序,我偶然发现了这个二合一问题,第一个问题导致另一个问题。我还没有找到一个问题,有人会同时遇到两个问题。我还在学习,并且从我遇到的其他问题中学到了很多东西,但是我找不到解决这个问题的方法。

这与线程有关。我想做一个线程,它可以每秒左右在富文本框中放置一些东西,而我仍然可以按下按钮来启动和停止它。但是要使线程可以运行的函数,我需要使函数静态。否则我会收到错误“字段初始化程序无法引用非静态字段、方法或属性”。但是当一个函数是静态的时,它不能访问任何创建的项目,比如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();
            }
        }
    }
}

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

提前感谢您的回答。

【问题讨论】:

  • 不要使用线程,使用计时器。它将解决这两个问题。

标签: multithreading winforms static field non-static


【解决方案1】:

但是要创建一个线程可以运行的函数,我需要创建 函数静态。

摆脱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 方法被标记为过时,将在 未来版本。

Thread.Suspend 和 Thread.Resume 方法不是 通常对应用程序有用,不应与 同步机制。因为 Thread.Suspend 和 Thread.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
    }

}

【讨论】:

  • 谢谢,这真的很有帮助。也感谢你让我知道暂停和恢复的事情,我会记住的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多