将函数从函数返回到bgWorker c#

时间:2012-09-18 14:52:47

标签: c# multithreading forms

编辑以便更好地理解......

我有一个Form1.cs文件和一个单独的Class.cs文件。

Form1中,我有一个调用Class.myFunc()的bgWorker,这会执行三个foreach循环,每个循环返回一些值,例如string ClientNamestring ClientOrder

我想将这些值从Class.myFunc返回到bgWorker(位于Form1内,请记住)并将它们插入到ListView,Textbox或其他任何内容中。

所以问题是:我如何将Class.myFunc中的字符串值返回给BgWorker?

我希望有人可以帮助我...

Form1.cs的

void bgWorker_DoWork(object sender, DoWorkEventArgs e)
{
    ControlsHelper.ControlInvike(listProcess, () => listProcess.Items.Add("Current").Name = "item1");
            myOtherClass cp = new myOtherClass();
            cp.myFunc();
}

Class.cs

public void myFunc()
{
    foreach (string Client in Clients)
    {
           // Do something
           // Return Client and insert into listview, richtextbox, W/E
    }
} 

3 个答案:

答案 0 :(得分:1)

你可以(ab)使用BackgroundWorker.ReportProgress来传递你的值作为第二个参数。

答案 1 :(得分:1)

扩展Daniel Hilgarth的回答:如果在Class.cs的上下文中不存在BGW,您不能将其作为参数传递,以便您可以更新进度。在您的DoWork签名中,object sender是要作为BackgroundWorker投射到myFunc的BGW。

所以你有

public void myFunc(BackgroundWorker bgw)
{
    foreach (string Client in Clients)
    {
       // Do something
       // Return Client and insert into listview, richtextbox, W/E

       var returningObjects = List<string>();  //I assume this will be a list of strings based on your question.
       returningObjects.Add(ClientName);
       returningObjects.Add(ClientOrder);
       returningObjects.Add(Client3rdThing);

       bgw.ReportProgress(0,returningObjects)
    }
} 

比使用通用List<string>更好,您可以创建自己的类,其中包含您需要的所有项目,然后您可以显式调用它们而不是引用列表索引。

void bgWorker_DoWork(object sender, DoWorkEventArgs e)
{
    BackgroundWorker bgw = sender as BackgroundWorker;
    ControlsHelper.ControlInvike(listProcess, () => listProcess.Items.Add("Current").Name = "item1");
            myOtherClass cp = new myOtherClass();
            cp.myFunc(bgw);
}

然后在ProgressChanged事件处理程序

private void bgWorker_ProgressChanged(object sender,
    ProgressChangedEventArgs e)
{
   //Set the  e.UserState to whatever you need. It is of type Object.
    var returnedObjects = e.Userstate as List<string>;
    if(returnedObjects != null)
    {
        //do stuff with each of your returnedObjects[i];
    }

}

为确保线程安全,我使用this扩展方法进行控制。将这个逻辑包含在扩展方法中真的很棒。无论何时需要调用它,都不需要考虑Invoke结构,只需要调用它即可。

当您使用

实例化BackgroundWorker时,请确保将它们组合在一起
bgWorker.ProgressChanged += new ProgressChangedEventHandler(bgWorker_ProgressChanged);

答案 2 :(得分:0)

首先,确保您确实需要多线程。您可能只需阻止GUI更新,直到列表加载完成为止。

如果确实需要多线程,请确保您的三个循环需要按该顺序运行。如果他们不是,那么你想要3 bgWorkers而不是1。

最后,有很多关于线程安全的好文章。您会发现无法直接更新列表视图,您必须使用线程安全代理。