如何使用BackgroundWorker在单独的线程中运行`object = ClassA.GetObject()`之类的任务?

时间:2012-08-13 14:53:23

标签: c# multithreading backgroundworker

我正在努力使这一行与BackgroundWorker

一起使用
map = Map.LoadMap(mapname);

...像这样:

bw.DoWork += (map = Map.LoadMap(mapname));

导致错误Cannot implicitly convert type 'game.Map' to 'System.ComponentModel.DoWorkEventHandler'

我刚刚开始使用BackgroundWorker作为游戏的线程组件,但看起来很难将所有现有方法转换为使用它。是否有一种简单的方法可以实现这一功能,还是更好地切换到其他一些线程机制?

注意:从线程基础我需要能够轮询进度百分比而不是搞乱我现有的方法调用。

5 个答案:

答案 0 :(得分:2)

您可以像这样利用anonymous delegates

bw.DoWork += (sender, args) => { map = Map.LoadMap(mapname); };

答案 1 :(得分:1)

Backgroundworker很好,因为您可以使用选项WorkerReportsProgress = true 这可用于汇集百分比

您可以像这样报告DoWork方法中的进度

bw.ReportProgress(percentage);

我用来将BackgroundWorker关联为Threads会做什么的包装器。所以我在GUI工作中使用BackgroundWorker,在更专业或更脏的工作(Windows服务等)上使用Threads

你的dowork方法必须像这样写

bw.DoWork += (sender, args) => { map = Map.LoadMap(mapname); };

答案 2 :(得分:1)

据我所知,变量映射的类型和方法Map.LoadMap的返回类型是game.Map。 在您的代码中

bw.DoWork += (map = Map.LoadMap(mapname));

你正在做下一步:从Map.LoadMap(mapname)获取结果,将其设置为变量map,然后尝试将此值用作DoWork事件的处理程序。变量映射和属性bw.DoWork的类型是不同的。

所以你只需要将这一行改为:

bw.DoWork += (sender, eventArgs) => { map = Map.LoadMap(mapname); }

这意味着您正在尝试创建新的委托“(sender,eventArgs)=> ...”并将其用作属性bw.DoWork的处理程序。

答案 3 :(得分:0)

您可以像这样使用BackgroundWorker:

        var worker = new System.ComponentModel.BackgroundWorker();
        worker.DoWork += delegate 
        { 
             map = Map.LoadMap(mapname); 
        };
        worker.RunWorkerAsync();

请记住,程序将在RunWorkerAsync()方法之后立即继续执行,因此如果之后使用map变量,它可能不会是加载的映射。

要在加载地图后继续执行,您还需要订阅RunWorkerCompleted:

        var worker = new System.ComponentModel.BackgroundWorker();
        worker.DoWork += delegate 
        { 
            map = Map.LoadMap(mapname); 
        };
        worker.RunWorkerCompleted += delegate 
        { 
            MapComplete(); // contiune with stuff here
        };
        worker.RunWorkerAsync();

答案 4 :(得分:0)

+ =运算符表示您正在附加事件处理程序(DoWork是一个事件)。

以下是一个示例用法:

创建一个backgroundworker的实例(在这种情况下它将在类级别),调用附加事件的函数 SetupBackgroundWorker()

private BackgroundWorker bw = new BackgroundWorker();

private void SetupBackgroundWorker()
{
    bw.DoWork += new DoWorkEventHandler(bw_DoWork);
    bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bw_RunWorkerCompleted);
    bw.ProgressChanged += new ProgressChangedEventHandler(bw_ProgressChanged);
    bw.ReportProgress = true;
}

这些是示例事件处理程序,应该给你一个想法

private void bw_ProgressChanged(object sender, ProgressChangedEventArgs e)
{//Just as an example, I don't ever call the functions to trigger this event
    int ProgressPercent = e.ProgressPercentage;
    object AnyOtherDataReported = e.UserState;
}
private void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
   //Do something when the work has been completed
   //Note: You should always check e.Cancelled and e.Error before attempting to touch the e.Result. I did not put that protection in this example.

   object TheResultFrom_DoWork = e.Result;//This is your "map" object
}
private void bw_DoWork(object sender, DoWorkEventArgs e)
{
  //object PassedInObject=e.Argument; //This is the argument you sent to RunWorkerAsync

    //Type cast PassedInObject to your correct Type
    WhateverTypeItIs_YouDidntSay mapname=(WhateverTypeItIs_YouDidntSay)e.Argument

    //Perform your task
    object returnvalue=Map.LoadMap(mapname);//This was your varriable called "map"

    //Assign the result of your task to the return value
    e.Result=returnvalue;
}

将此函数传递给 mapname 的值,如果后台工作人员没有忙于执行上一个任务,则应该启动该过程。

private void ProcessTheMap_InBackground(WhateverTypeItIs_YouDidntSay mapname)
{
    if (!bw.IsBusy)
    {
        bw.RunWorkerAsync(mapname);
    }
    else
    {//You are already loading something in the background
    }
}