具有检索值的函数的反交叉线程

时间:2014-12-12 10:09:49

标签: c# multithreading

我一直在谷歌搜索并尝试一些不同的方法,但没有一个正在发挥作用。

Using an anti-cross-thread function to return a value

Cross-thread operation not valid: Control 'textBox1' accessed from a thread other than the thread it was created on

C# Return value from function invoked in thread

http://www.dreamincode.net/forums/topic/188209-cross-thread-calls-made-easy/

我的代码(非常简短)如下:

public partial class print : Form {

    ListView _listOfCategories = new ListView();
    delegate string getNameOfPrinterCallBack(string name);

     private string getNameOfPrinter(string name){
        ListViewItem search = new ListViewItem();

        if (this._listOfCategories.InvokeRequired)
        {
            getNameOfPrinterCallBack cb = new getNameOfPrinterCallBack(getNameOfPrinter);

            return (string)Invoke(cb, new object[] { name });
        }
        else {

            search = this._listOfCategories.FindItemWithText(name, false, 0);

            return this._listOfCategories.Items[search.Index].SubItems[1].Text;
        }
    }
}

我在一个计时器中调用函数getNameOfPrinter(5秒内5秒)。它第一次正常工作,第二次进一步开始给我错误:

  

未处理的类型' System.StackOverflowException'   发生在System.Windows.Forms.dll

打印错误的行是return (string)Invoke(cb, new object[] { name });

这是因为我试图实现一种避免交叉线程错误的方法。我的代码出了什么问题?

2 个答案:

答案 0 :(得分:1)

this._listOfCategories.InvokeRequired评估为真时,您将进入无限循环(此时您正在回忆自己,InvokeRequired将始终为真。)

将您的模式更改为以下内容,这应该会有所帮助:

    private void OnSomeTimerEvent(object sender, EventArgs e)
    {
        Action action = new Action(() =>
        {
            // Do your UI control item processing here. Don't recall this method!
        });

        if (this.InvokeRequired)
        {
            // or Use BeginInvoke if you don't want the caller to block (post the message 
            // onto the UI's message pump and will get processed asynchronously).
            this.Invoke(action);
        }
        else
        {
            action();
        }
    }

答案 1 :(得分:0)

解决。

if (this._listOfCategories.InvokeRequired)
{
    getNameOfPrinterCallBack cb = new getNameOfPrinterCallBack(getNameOfPrinter);

    return (string)this._listOfCategories.Invoke(cb, name);
}
else {

    search = this._listOfCategories.FindItemWithText(name, false, 0);

    return this._listOfCategories.Items[search.Index].SubItems[1].Text;
}