非静态字段方法或属性/字段初始值设定项不能引用非静态字段方法或属性

时间:2015-08-04 20:08:43

标签: multithreading winforms static field non-static

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

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

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

提前感谢您的答案。

1 个答案:

答案 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
    }

}