2

我正在尝试使这条线与BackgroundWorker

map = Map.LoadMap(mapname);

…像这样:

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

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

我刚开始BackgroundWorker在我的游戏中使用线程组件,但看起来将所有现有方法转换为使用它并不容易。有没有一种简单的方法可以完成这项工作,还是切换到其他线程机制更好?

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

4

5 回答 5

2

您可以像这样利用匿名代表

bw.DoWork += (sender, args) => { map = Map.LoadMap(mapname); };
于 2012-08-13T14:59:05.337 回答
1

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

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

bw.ReportProgress(percentage);

我曾经将 BackgroundWorker 关联为 Threads 的包装器。所以我在 GUI 工作上使用 BackgroundWorker,在更专业或肮脏的工作(Windows 服务等)上使用线程

你的dowork方法必须这样写

bw.DoWork += (sender, args) => { map = Map.LoadMap(mapname); };
于 2012-08-13T14:58:32.283 回答
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 的处理程序。

于 2012-08-13T15:03:34.067 回答
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();
于 2012-08-13T15:20:17.890 回答
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
    }
}
于 2012-08-13T15:21:30.387 回答