0

我在 C# 中的线程有一个非常烦人的问题。使用此代码时,我收到错误“字段初始化程序无法引用非静态字段、方法或属性'Scraper.Form1.scrapeStart()'”:

public partial class Form1 : Form
{
    public Thread scrape = new Thread(() => scrapeStart()); //This is where the error happens
    public About about = new About();
    public Form1()
    {
        InitializeComponent();
    }

    public void appendOutput(String s)
    {
        output.AppendText(s);
        output.SelectionStart = output.Text.Length;
        output.ScrollToCaret();
        output.Refresh();
    }

    public void scrapeStart(){
        Button button1 = new Button();
        appendOutput("");
        button1.Enabled = true;
    }

    private void button3_Click(object sender, EventArgs e)
    {
        about.ShowDialog();
    }

    private void button1_Click(object sender, EventArgs e)
    {
        button1.Enabled = false;
        scrape.Start();
    }

    private void button2_Click(object sender, EventArgs e)
    {
        scrape.Abort();
        button1.Enabled = true;
    }
}

我意识到如果我将函数 scrapeStart 设为静态它会起作用,但这会使 appendOutput(""); 和 button1.Enabled = true 抛出错误。如果我将新线程放在它开始的位置(button1_Click),那么它不能在 button2_Click 中中止。

我对 C# 有点了解,所以我可能做的所有事情都非常错误,或者这可能只是一个小问题。但无论哪种方式,有人可以帮助我吗?

4

2 回答 2

10

这实际上与线程无关。如果你写,你会看到完全相同的问题:

public class Foo
{
    int x = 10;
    int y = x;   
}

或者更清楚:

public class Bar
{
    object obj = this;
}

这里有一点让人分心的是,this引用是隐式的——你正在创建一个目标为this.

解决方案就是将赋值放入构造函数中:

public Thread scrape;
public About about = new About();
public Form1()
{
    InitializeComponent();
    scrape = new Thread(scrapeStart);
}

作为旁白:

  • 请不要使用公共领域!
  • 请遵守 .NET 命名约定
  • 需要修复scrapeStart不应直接访问 UI 元素的线程部分
于 2012-09-30T07:43:55.473 回答
0

我认为您需要使用 InvokeRequired。

public void scrapeStart()
{
    if (InvokeRequired)
    {
    this.Invoke(new Action(scrapeStart));
    return;
    }
    Button button1 = new Button();
    appendOutput("");
    button1.Enabled = true;
}
于 2012-09-30T07:48:58.093 回答