如何让BackgroundWorker返回一个对象

发布于 2024-07-23 04:35:58 字数 113 浏览 13 评论 0原文

我需要使 RunWorkerAsync() 返回 List

能够从后台工作者返回对象的过程是什么?

I need to make RunWorkerAsync() return a List<FileInfo>.

What is the process to be able to return an object from a background worker?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

半边脸i 2024-07-30 04:35:58

BackgroundWorker(后台工作发生的地方)的 DoWork 事件处理程序中,有一个参数 DoWorkEventArgs。 该对象有一个公共属性对象 Result。 当您的工作线程生成其结果(在您的情况下为 List)时,将 e.Result 设置为该结果,然后返回。

现在您的BackgroundWorker 已完成其任务,它会触发RunWorkerCompleted 事件,该事件有一个RunWorkerCompletedEventArgs 对象作为参数。 RunWorkerCompletedEventArgs.Result 将包含来自 BackgroundWorker 的结果。

例子:

private void bgw_DoWork(object sender, DoWorkEventArgs e)
{
    int result = 2+2;
    e.Result = result;
}

private void bgw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
    int result = (int)e.Result;
    MessageBox.Show("Result received: " + result.ToString());
}

In your DoWork event handler for the BackgroundWorker (which is where the background work takes place) there is an argument DoWorkEventArgs. This object has a public property object Result. When your worker has generated its result (in your case, a List<FileInfo>), set e.Result to that, and return.

Now that your BackgroundWorker has completed its task, it triggers the RunWorkerCompleted event, which has a RunWorkerCompletedEventArgs object as an argument. RunWorkerCompletedEventArgs.Result will contain the result from your BackgroundWorker.

example:

private void bgw_DoWork(object sender, DoWorkEventArgs e)
{
    int result = 2+2;
    e.Result = result;
}

private void bgw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
    int result = (int)e.Result;
    MessageBox.Show("Result received: " + result.ToString());
}
懒的傷心 2024-07-30 04:35:58

我假设您不想阻止并等待 RunWorkerAsync() 的结果(如果您这样做,就没有理由运行异步!

如果您想在后台进程完成时收到通知,请挂钩 RunWorkerCompleted 。如果要返回某些状态,请在 DoWork 事件参数的 Result 成员中返回它。

事件



    private void BackgroundWorker_DoWork(object sender, DoWorkEventArgs e)
    {
      // do your thing
      ....
      // return results
      e.Result = theResultObject;
    }
    
    // now get your results
    private void BackgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
      MyResultObject result = (MyResultObject)e.Result;
      // process your result...
    }


I'm assuming that you don't want to block and wait on RunWorkerAsync() for the results (if you did, there would be no reason to run async!

If you want to be notified when the background process finishes, hook the RunWorkerCompleted Event. If you want to return some state, return it in the Result member of DoWork's event args.

Example:



    private void BackgroundWorker_DoWork(object sender, DoWorkEventArgs e)
    {
      // do your thing
      ....
      // return results
      e.Result = theResultObject;
    }
    
    // now get your results
    private void BackgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
      MyResultObject result = (MyResultObject)e.Result;
      // process your result...
    }


梅窗月明清似水 2024-07-30 04:35:58

RunWorkerAsync() 异步启动进程,并在进程实际完成之前返回并继续执行代码。 如果您想获取 BackgroundWorker 的结果,则需要创建一个实例变量来保存该值,并在 BackgroundWorker 完成后检查它。

如果您想等到工作完成,那么您不需要 BackgroundWorker

RunWorkerAsync() starts the process asynchronously and will return and continue executing your code before the process actually completes. If you want to obtain the result of the BackgroundWorker, you'll need to create an instance variable to hold that value and check it once the BackgroundWorker completes.

If you want to wait until the work is finished, then you don't need a BackgroundWorker.

谈情不如逗狗 2024-07-30 04:35:58

为了补充大卫的答案,人们可​​能想要推送一个元组来为方法提供多个参数。

为此,让我更新他的答案,其中通过每个调用传递一个值(称为engagementId),并且元组保存要使用的原始项目以及结果。

private void bgw_DoWork(object sender, DoWorkEventArgs e)
{
    var engagementId = (int)e.Argument;
    int result = 2 + 2;
    e.Result = (engagementId, result);
}

private void bgw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
    (int engagementId, int result) tupleResult = ((int, int)) e.Result; // Both (( are needed for tuple/casting.

    MessageBox.Show($"Result received {tupleResult.result} for engagement {tupleResult.engagementId}");
}

有关详细信息,请参阅如何转换为元组的答案。

To add to David's answer, one may want to push a tuple through to provide more than one argument to the methods.

To do so let me update his answer, where a value (called engagementId) is passed through each of the calls and the tuple holds that original item for use as well as the result.

private void bgw_DoWork(object sender, DoWorkEventArgs e)
{
    var engagementId = (int)e.Argument;
    int result = 2 + 2;
    e.Result = (engagementId, result);
}

private void bgw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
    (int engagementId, int result) tupleResult = ((int, int)) e.Result; // Both (( are needed for tuple/casting.

    MessageBox.Show(
quot;Result received {tupleResult.result} for engagement {tupleResult.engagementId}");
}

See the answer to How To Cast To A Tuple for more information.

殤城〤 2024-07-30 04:35:58

根据您的模型,您要么希望工作线程在完成工作时回调到其创建者(或其他进程),要么必须经常轮询工作线程以查看它是否已完成,如果所以,得到结果。

等待工作线程返回其结果的想法破坏了多线程的好处。

Depending on your model, you either want to have your worker thread call back to its creator (or to some other process) when it's finished its work, or you have to poll the worker thread every so often to see if it's done and, if so, get the result.

The idea of waiting for a worker thread to return its result undermines the benefits of multithreading.

辞旧 2024-07-30 04:35:58

您可以让您的线程引发一个以对象作为参数的事件:

ThreadFinishedEvent(this, new ThreadEventArgs(object));

其中:

public class ThreadEventArgs : EventArgs
{
    public ThreadEventArgs(object object)
    {
        Object = object
    }

    public object Object
    {
        get; private set;
    }
}

You could have your thread raise an event with the object as an argument:

ThreadFinishedEvent(this, new ThreadEventArgs(object));

where:

public class ThreadEventArgs : EventArgs
{
    public ThreadEventArgs(object object)
    {
        Object = object
    }

    public object Object
    {
        get; private set;
    }
}
过气美图社 2024-07-30 04:35:58

一般来说,当异步运行进程时,工作线程应该调用委托或触发事件(如 ChrisF)。

您可以查看新的 PFX,它具有一些可以返回值的并发函数。

例如,有一个名为 Parallel.ForEach() 的函数,它具有可以返回值的重载。

查看此内容以获取更多信息

http://msdn.microsoft.com/en-us/magazine/cc817396.aspx

Generally speaking when running a process async, The worker thread should call a delegate or fire an event (like ChrisF).

You can check out the new PFX which has some concurrency function that can return values.

For example there is a function called Parallel.ForEach() which has an overload that can return a value.

check this out for more info

http://msdn.microsoft.com/en-us/magazine/cc817396.aspx

风追烟花雨 2024-07-30 04:35:58

不要在“DoWork”方法中进行后台工作,而是创建一个返回您想要返回的类型的方法,并将其应用到 e.Result,如此处建议的其他答案所示。 作为回答 OP 问题而不使问题过于复杂的最小示例...

        private List<FileInfo> FileInfoWorker(object sender, DoWorkEventArgs e)
    {
        return new List<FileInfo>(new DirectoryInfo("C:\\SOTest").GetFiles().ToList());
    }

    private void bgwTest_DoWork(object sender, DoWorkEventArgs e)
    {
        BackgroundWorker worker = sender as BackgroundWorker;

        e.Result = FileInfoWorker(worker, e);
    }

    private void bgwTest_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        if (e.Error != null)
        {
            MessageBox.Show(e.Error.Message);
        }
        else if (e.Cancelled)
        {
            tbStatus.Text = "Background operation cancelled.";
        }
        else
        {
            tbStatus.Text = "Background operation complete.";
        }
    }

该示例还演示了如何从 BackgroundWorker API 更新 TextBox。 未显示的是对通过 ProgressBar 和 TextBoxes 报告进度的支持以及对取消的支持,API 也支持这两者。 该代码是通过按钮运行的...

        private void btnSOTest_Click(object sender, EventArgs e)
    {
        bgwTest.RunWorkerAsync();
    }

Instead of doing the background work in the "DoWork" method, create a method that returns the type you want to return and apply that to e.Result as other answers here recommend. As a minimal example that answers the OP's question without overcomplicating the matter...

        private List<FileInfo> FileInfoWorker(object sender, DoWorkEventArgs e)
    {
        return new List<FileInfo>(new DirectoryInfo("C:\\SOTest").GetFiles().ToList());
    }

    private void bgwTest_DoWork(object sender, DoWorkEventArgs e)
    {
        BackgroundWorker worker = sender as BackgroundWorker;

        e.Result = FileInfoWorker(worker, e);
    }

    private void bgwTest_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        if (e.Error != null)
        {
            MessageBox.Show(e.Error.Message);
        }
        else if (e.Cancelled)
        {
            tbStatus.Text = "Background operation cancelled.";
        }
        else
        {
            tbStatus.Text = "Background operation complete.";
        }
    }

The example also shows how to update a TextBox from the BackgroundWorker API. Not shown is support for reporting progress via a ProgressBar and TextBoxes and support for cancellation, both are also supported in the API. The code is ran via a button...

        private void btnSOTest_Click(object sender, EventArgs e)
    {
        bgwTest.RunWorkerAsync();
    }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文