如何正确等待BackgroundWorker完成?

发布于 2024-08-03 03:54:06 字数 1681 浏览 10 评论 0原文

观察下面的代码:

var handler = GetTheRightHandler();
var bw = new BackgroundWorker();
bw.RunWorkerCompleted += OnAsyncOperationCompleted;
bw.DoWork += OnDoWorkLoadChildren;
bw.RunWorkerAsync(handler);

现在假设我想等到 bw 完成工作。这样做的正确方法是什么?

我的解决方案是这样的:

bool finished = false;
var handler = GetTheRightHandler();
var bw = new BackgroundWorker();
bw.RunWorkerCompleted += (sender, args) =>
{
  OnAsyncOperationCompleted(sender, args);
  finished = true;
});
bw.DoWork += OnDoWorkLoadChildren;
bw.RunWorkerAsync(handler);
int timeout = N;
while (!finished && timeout > 0)
{
  Thread.Sleep(1000);
  --timeout;
}
if (!finished)
{
  throw new TimedoutException("bla bla bla");
}

但我不喜欢它。

我考虑过用同步事件替换 finished 标志,将其设置在 RunWorkerCompleted 处理程序中,并稍后阻止它,而不是执行 while-sleep 循环。

唉,这是错误的,因为代码可能在 WPF 或 WindowsForm 同步上下文中运行,在这种情况下,我会阻塞与 RunWorkerCompleted 处理程序运行的同一线程,这显然不是很明智的举动。

我想知道更好的解决方案。

谢谢。

编辑:

PS

  • 示例代码是故意设计来澄清我的问题的。我完全知道完成回调,但我想知道如何等待完成。这是我的问题。
  • 我知道 Thread.JoinDelegate.BeginInvokeThreadPool.QueueUserWorkItem 等...这个问题具体是关于 BackgroundWorker

编辑2:

好的,我想如果我解释一下这个场景会容易得多。

我有一个单元测试方法,它调用一些异步代码,而这些代码最终又会调用一个 BackgroundWorker ,我可以将完成处理程序传递给它。所有代码都是我的,因此如果我愿意,我可以更改实现。 不过,我不会替换 BackgroundWorker,因为它会自动使用正确的同步上下文,这样当在 UI 线程上调用代码时,就会在同一 UI 线程上调用完成回调,这非常好。

不管怎样,单元测试方法有可能在 BW 完成工作之前就结束了,这是不好的。所以我想等到 BW 完成并想知道最好的方法。

还有更多的部分,但总体情况或多或少像我刚才描述的那样。

Observe the following piece of code:

var handler = GetTheRightHandler();
var bw = new BackgroundWorker();
bw.RunWorkerCompleted += OnAsyncOperationCompleted;
bw.DoWork += OnDoWorkLoadChildren;
bw.RunWorkerAsync(handler);

Now suppose I want to wait until bw finishes working. What is the right way to do so?

My solution is this:

bool finished = false;
var handler = GetTheRightHandler();
var bw = new BackgroundWorker();
bw.RunWorkerCompleted += (sender, args) =>
{
  OnAsyncOperationCompleted(sender, args);
  finished = true;
});
bw.DoWork += OnDoWorkLoadChildren;
bw.RunWorkerAsync(handler);
int timeout = N;
while (!finished && timeout > 0)
{
  Thread.Sleep(1000);
  --timeout;
}
if (!finished)
{
  throw new TimedoutException("bla bla bla");
}

But I do not like it.

I have considered replacing the finished flag with a synchronization event, set it in the RunWorkerCompleted handler and block on it later instead of doing the while-sleep loop.

Alas, it is wrong, because the code may run in the WPF or WindowsForm synchronization context, in which case I would block the same thread as the RunWorkerCompleted handler runs on, which is clearly not very smart move.

I would like to know of a better solution.

Thanks.

EDIT:

P.S.

  • The sample code is so contrived intentionally to clarify my question. I am perfectly aware of the completion callback and yet I want to know how to wait till completion. That is my question.
  • I am aware of Thread.Join, Delegate.BeginInvoke, ThreadPool.QueueUserWorkItem, etc... The question is specifically about BackgroundWorker.

EDIT 2:

OK, I guess it will be much easier if I explain the scenario.

I have a unit test method, which invokes some asynchronous code, which in turn ultimately engages a BackgroundWorker to which I am able to pass a completion handler. All the code is mine, so I can change the implementation if I wish to.
I am not going, however, to replace the BackgroundWorker, because it automatically uses the right synchronization context, so that when the code is invoked on a UI thread the completion callback is invoked on the same UI thread, which is very good.

Anyway, it is possible that the unit test method hits the end before the BW finishes its work, which is not good. So I wish to wait until the BW completes and would like to know the best way for it.

There are more pieces to it, but the overall picture is more or less like I have just described.

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

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

发布评论

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

评论(10

标点 2024-08-10 03:54:06

尝试像这样使用 AutoResetEvent 类:

var doneEvent = new AutoResetEvent(false);
var bw = new BackgroundWorker();

bw.DoWork += (sender, e) =>
{
  try
  {
    if (!e.Cancel)
    {
      // Do work
    }
  }
  finally
  {
    doneEvent.Set();
  }
};

bw.RunWorkerAsync();
doneEvent.WaitOne();

警告:您应该确保无论发生什么情况都会调用 doneEvent.Set()。此外,您可能希望为 doneEvent.WaitOne() 提供指定超时时间的参数。

注意:此代码几乎是 Fredrik Kalseth 回答 类似问题

Try using the AutoResetEvent class like this:

var doneEvent = new AutoResetEvent(false);
var bw = new BackgroundWorker();

bw.DoWork += (sender, e) =>
{
  try
  {
    if (!e.Cancel)
    {
      // Do work
    }
  }
  finally
  {
    doneEvent.Set();
  }
};

bw.RunWorkerAsync();
doneEvent.WaitOne();

Caution: You should make sure that doneEvent.Set() is called no matter what happens. Also you might want to provide the doneEvent.WaitOne() with an argument specifying a timeout period.

Note: This code is pretty much a copy of Fredrik Kalseth answer to a similar question.

岁月蹉跎了容颜 2024-08-10 03:54:06

要等待后台工作线程(单个或多个),请执行以下操作:

  1. 创建您以编程方式创建的后台工作线程的列表:

    私有IList m_WorkersWithData = new List();
    
  2. 在列表中添加后台工作人员:

    BackgroundWorker工人=新的BackgroundWorker();
    worker.DoWork += new DoWorkEventHandler(worker_DoWork);
    worker.ProgressChanged += new ProgressChangedEventHandler(worker_ProgressChanged);
    工人.WorkerReportsProgress = true;
    m_WorkersWithData.Add(worker);
    Worker.RunWorkerAsync();
    
  3. 使用以下函数等待列表中的所有worker:

    private void CheckAllThreadsHaveFinishedWorking()
    {
        布尔 hasAllThreadsFinished = false;
        while (!hasAllThreadsFinished)
        {
            hasAllThreadsFinished =(来自 m_WorkersWithData 中的工作人员
                                     哪里worker.IsBusy
                                     选择工人).ToList().Count == 0;
            应用程序.DoEvents(); //如果你想要有进度条并且想要更新它,这个调用非常重要
                                    //来自后台工作者的Progress事件。
            线程.睡眠(1000); //如果循环继续,则此调用将等待,确保之前释放了 CPU 时间
                                    //重新检查。
        }
        m_WorkersWithData.Clear(); //循环退出后清除所有后台worker列表以释放内存。
                                    //相反你也可以处置你的后台工作者。
    }
    

To wait for a background worker thread (single or multiple) do the following:

  1. Create a List of Background workers you have programatically created:

    private IList<BackgroundWorker> m_WorkersWithData = new List<BackgroundWorker>();
    
  2. Add the background worker in the list:

    BackgroundWorker worker = new BackgroundWorker();
    worker.DoWork += new DoWorkEventHandler(worker_DoWork);
    worker.ProgressChanged += new ProgressChangedEventHandler(worker_ProgressChanged);
    worker.WorkerReportsProgress = true;
    m_WorkersWithData.Add(worker);
    worker.RunWorkerAsync();
    
  3. Use the following function to wait for all workers in the List:

    private void CheckAllThreadsHaveFinishedWorking()
    {
        bool hasAllThreadsFinished = false;
        while (!hasAllThreadsFinished)
        {
            hasAllThreadsFinished = (from worker in m_WorkersWithData
                                     where worker.IsBusy
                                     select worker).ToList().Count == 0;
            Application.DoEvents(); //This call is very important if you want to have a progress bar and want to update it
                                    //from the Progress event of the background worker.
            Thread.Sleep(1000);     //This call waits if the loop continues making sure that the CPU time gets freed before
                                    //re-checking.
        }
        m_WorkersWithData.Clear();  //After the loop exits clear the list of all background workers to release memory.
                                    //On the contrary you can also dispose your background workers.
    }
    
一抹苦笑 2024-08-10 03:54:06

BackgroundWorker 有一个完成事件。不要等待,而是从完成处理程序中调用剩余的代码路径。

BackgroundWorker has a completion event. Instead of waiting, call your remaining code path from the completion handler.

Hello爱情风 2024-08-10 03:54:06

这个问题很老了,但我认为作者没有得到他想要的答案。

这有点脏,它是在 vb.NET 中,但对我有用

Private Sub MultiTaskingForThePoor()
    Try
        'Start background worker
        bgwAsyncTasks.RunWorkerAsync()
        'Do some other stuff here
        For i as integer = 0 to 100
            lblOutput.Text = cstr(i)
        Next

        'Wait for Background worker
        While bgwAsyncTasks.isBusy()
            Windows.Forms.Application.DoEvents()
        End While

        'Voila, we are back in sync
        lblOutput.Text = "Success!"
    Catch ex As Exception
        MsgBox("Oops!" & vbcrlf & ex.Message)
    End Try
End Sub

This question is old but I don't think the author got the answer he was looking for.

This is a bit dirty, and it's in vb.NET but works for me

Private Sub MultiTaskingForThePoor()
    Try
        'Start background worker
        bgwAsyncTasks.RunWorkerAsync()
        'Do some other stuff here
        For i as integer = 0 to 100
            lblOutput.Text = cstr(i)
        Next

        'Wait for Background worker
        While bgwAsyncTasks.isBusy()
            Windows.Forms.Application.DoEvents()
        End While

        'Voila, we are back in sync
        lblOutput.Text = "Success!"
    Catch ex As Exception
        MsgBox("Oops!" & vbcrlf & ex.Message)
    End Try
End Sub
有深☉意 2024-08-10 03:54:06

使用 Application.DoEvents() 在循环中检查 backgrWorker.IsBusy 并不是一个好方法。

我同意@JohannesH,你应该明确使用 AutoResetEvent 作为一个优雅的解决方案。但不要在UI Thread中使用,会导致主线程阻塞;它应该来自另一个后台工作线程。

AutoResetEvent aevent = new AutoResetEvent(false);    
private void button1_Click(object sender, EventArgs e)
{
    bws = new BackgroundWorker();
    bws.DoWork += new DoWorkEventHandler(bw_work);
    bws.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bw_complete);
    bws.RunWorkerAsync();

    bwWaiting.DoWork += new DoWorkEventHandler(waiting_work);
    bwWaiting.RunWorkerCompleted += new RunWorkerCompletedEventHandler(waiting_complete);
    bwWaiting.RunWorkerAsync();
}

void bw_work(object sender, DoWorkEventArgs e)
{
    Thread.Sleep(2000);
}

void bw_complete(object sender, RunWorkerCompletedEventArgs e)
{
    Debug.WriteLine("complete " + bwThread.ToString());
    aevent.Set();
}
void waiting_work(object sender, DoWorkEventArgs e)
{
    aevent.WaitOne();
}

void waiting_complete(object sender, RunWorkerCompletedEventArgs e)
{
    Debug.WriteLine("complete waiting thread");
}

Checking backgrWorker.IsBusy in the loop with Application.DoEvents() is not a nicely way.

I agree with @JohannesH, you should definitively use AutoResetEvent as a elegant solution. But not using it in UI Thread, it will cause main thread blocked; it should come from another background worker thread.

AutoResetEvent aevent = new AutoResetEvent(false);    
private void button1_Click(object sender, EventArgs e)
{
    bws = new BackgroundWorker();
    bws.DoWork += new DoWorkEventHandler(bw_work);
    bws.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bw_complete);
    bws.RunWorkerAsync();

    bwWaiting.DoWork += new DoWorkEventHandler(waiting_work);
    bwWaiting.RunWorkerCompleted += new RunWorkerCompletedEventHandler(waiting_complete);
    bwWaiting.RunWorkerAsync();
}

void bw_work(object sender, DoWorkEventArgs e)
{
    Thread.Sleep(2000);
}

void bw_complete(object sender, RunWorkerCompletedEventArgs e)
{
    Debug.WriteLine("complete " + bwThread.ToString());
    aevent.Set();
}
void waiting_work(object sender, DoWorkEventArgs e)
{
    aevent.WaitOne();
}

void waiting_complete(object sender, RunWorkerCompletedEventArgs e)
{
    Debug.WriteLine("complete waiting thread");
}
—━☆沉默づ 2024-08-10 03:54:06

VB.NET

While BackgroundWorker1.IsBusy()
    Windows.Forms.Application.DoEvents()
End While

您可以使用它来链接多个事件。 (接下来的伪代码)

download_file("filepath")

    While BackgroundWorker1.IsBusy()
       Windows.Forms.Application.DoEvents()
    End While
'Waits to install until the download is complete and lets other UI events function install_file("filepath")
While BackgroundWorker1.IsBusy()
    Windows.Forms.Application.DoEvents()
End While
'Waits for the install to complete before presenting the message box
msgbox("File Installed")

VB.NET

While BackgroundWorker1.IsBusy()
    Windows.Forms.Application.DoEvents()
End While

You can use this to chain multiple events. (pseudo code to follow)

download_file("filepath")

    While BackgroundWorker1.IsBusy()
       Windows.Forms.Application.DoEvents()
    End While
'Waits to install until the download is complete and lets other UI events function install_file("filepath")
While BackgroundWorker1.IsBusy()
    Windows.Forms.Application.DoEvents()
End While
'Waits for the install to complete before presenting the message box
msgbox("File Installed")
孤寂小茶 2024-08-10 03:54:06

不太确定你所说的等待是什么意思。您的意思是您希望(由 BW)完成某件事,完成后您想做其他事情吗?
像您一样使用 bw.RunWorkerCompleted (使用单独的函数以提高可读性),并在该回调函数中执行下一步操作。
启动计时器来检查工作是否不会花费太长时间。

var handler = GetTheRightHandler();
var bw = new BackgroundWorker();
bw.RunWorkerCompleted += (sender, args) =>
{
  OnAsyncOperationCompleted(sender, args);
});
bw.DoWork += OnDoWorkLoadChildren;
bw.RunWorkerAsync(handler);

Timer Clock=new Timer();
Clock.Interval=1000;
Clock.Start();
Clock.Tick+=new EventHandler(Timer_Tick);

public void Timer_Tick(object sender,EventArgs eArgs)
{   
    if (bw.WorkerSupportsCancellation == true)
    {
        bw.CancelAsync();
    }

    throw new TimedoutException("bla bla bla");
 }

在 OnDoWorkLoadChildren 中:

if ((worker.CancellationPending == true))
{
    e.Cancel = true;
    //return or something
}

not quite sure what u mean by waiting. Do you mean that you want something done (by the BW) after thats done you want to do something else?
Use bw.RunWorkerCompleted like you do (use a seperate function for readability) and in that callback function do you next stuff.
Start a timer to check if the work doesnt take too long.

var handler = GetTheRightHandler();
var bw = new BackgroundWorker();
bw.RunWorkerCompleted += (sender, args) =>
{
  OnAsyncOperationCompleted(sender, args);
});
bw.DoWork += OnDoWorkLoadChildren;
bw.RunWorkerAsync(handler);

Timer Clock=new Timer();
Clock.Interval=1000;
Clock.Start();
Clock.Tick+=new EventHandler(Timer_Tick);

public void Timer_Tick(object sender,EventArgs eArgs)
{   
    if (bw.WorkerSupportsCancellation == true)
    {
        bw.CancelAsync();
    }

    throw new TimedoutException("bla bla bla");
 }

In the OnDoWorkLoadChildren:

if ((worker.CancellationPending == true))
{
    e.Cancel = true;
    //return or something
}
木有鱼丸 2024-08-10 03:54:06

我也在寻找合适的解决方案。我用独占锁解决了等待。代码中的关键路径是写入公共容器(此处为控制台)并增加或减少工作人员。写入此变量时任何线程都不应干扰,否则计数将不再得到保证。

public class Program
{
    public static int worker = 0;
    public static object lockObject = 0;

    static void Main(string[] args)
    {

        BackgroundworkerTest backgroundworkerTest = new BackgroundworkerTest();
        backgroundworkerTest.WalkDir("C:\\");
        while (backgroundworkerTest.Worker > 0)
        {
            // Exclusive write on console
            lock (backgroundworkerTest.ExclusiveLock)
            {
                Console.CursorTop = 4; Console.CursorLeft = 1;
                var consoleOut = string.Format("Worker busy count={0}", backgroundworkerTest.Worker);
                Console.Write("{0}{1}", consoleOut, new string(' ', Console.WindowWidth-consoleOut.Length));
            }
        }
    }
}

public class BackgroundworkerTest
{
    private int worker = 0;
    public object ExclusiveLock = 0;

    public int Worker
    {
        get { return this.worker; }
    }

    public void WalkDir(string dir)
    {
        // Exclusive write on console
        lock (this.ExclusiveLock)
        {
            Console.CursorTop = 1; Console.CursorLeft = 1;
            var consoleOut = string.Format("Directory={0}", dir);
            Console.Write("{0}{1}", consoleOut, new string(' ', Console.WindowWidth*3 - consoleOut.Length));
        }

        var currentDir = new System.IO.DirectoryInfo(dir);
        DirectoryInfo[] directoryList = null;
        try
        {
            directoryList = currentDir.GetDirectories();
        }
        catch (UnauthorizedAccessException unauthorizedAccessException)
        {
            // No access to this directory, so let's leave
            return;
        }

        foreach (var directoryInfo in directoryList)
        {
            var bw = new BackgroundWorker();

            bw.RunWorkerCompleted += (sender, args) =>
            {
                // Make sure that this worker variable is not messed up
                lock (this.ExclusiveLock)
                {
                    worker--;
                }
            };

            DirectoryInfo info = directoryInfo;
            bw.DoWork += (sender, args) => this.WalkDir(info.FullName);

            lock (this.ExclusiveLock)
            {
                // Make sure that this worker variable is not messed up
                worker++;
            }
            bw.RunWorkerAsync();
        }
    }
}

I was also looking for a suitable solution. I solved the waiting with an exclusive lock. The critical path in code are writing to a public container (here the console) and increasing or decreasing the workers. No thread should interfere while writing to this variable, otherwise the count is not guaranteed anymore.

public class Program
{
    public static int worker = 0;
    public static object lockObject = 0;

    static void Main(string[] args)
    {

        BackgroundworkerTest backgroundworkerTest = new BackgroundworkerTest();
        backgroundworkerTest.WalkDir("C:\\");
        while (backgroundworkerTest.Worker > 0)
        {
            // Exclusive write on console
            lock (backgroundworkerTest.ExclusiveLock)
            {
                Console.CursorTop = 4; Console.CursorLeft = 1;
                var consoleOut = string.Format("Worker busy count={0}", backgroundworkerTest.Worker);
                Console.Write("{0}{1}", consoleOut, new string(' ', Console.WindowWidth-consoleOut.Length));
            }
        }
    }
}

public class BackgroundworkerTest
{
    private int worker = 0;
    public object ExclusiveLock = 0;

    public int Worker
    {
        get { return this.worker; }
    }

    public void WalkDir(string dir)
    {
        // Exclusive write on console
        lock (this.ExclusiveLock)
        {
            Console.CursorTop = 1; Console.CursorLeft = 1;
            var consoleOut = string.Format("Directory={0}", dir);
            Console.Write("{0}{1}", consoleOut, new string(' ', Console.WindowWidth*3 - consoleOut.Length));
        }

        var currentDir = new System.IO.DirectoryInfo(dir);
        DirectoryInfo[] directoryList = null;
        try
        {
            directoryList = currentDir.GetDirectories();
        }
        catch (UnauthorizedAccessException unauthorizedAccessException)
        {
            // No access to this directory, so let's leave
            return;
        }

        foreach (var directoryInfo in directoryList)
        {
            var bw = new BackgroundWorker();

            bw.RunWorkerCompleted += (sender, args) =>
            {
                // Make sure that this worker variable is not messed up
                lock (this.ExclusiveLock)
                {
                    worker--;
                }
            };

            DirectoryInfo info = directoryInfo;
            bw.DoWork += (sender, args) => this.WalkDir(info.FullName);

            lock (this.ExclusiveLock)
            {
                // Make sure that this worker variable is not messed up
                worker++;
            }
            bw.RunWorkerAsync();
        }
    }
}
享受孤独 2024-08-10 03:54:06

我将 任务BackgroundWorker

您可以创建任意数量的任务并将其添加到任务列表。
Worker 将在添加任务时启动,如果在 Worker IsBusy 期间添加任务则重新启动,并在没有更多任务时停止。

这将允许您根据需要异步更新 GUI,而不会冻结它。

这对我来说是有效的。

    // 'tasks' is simply List<Task> that includes events for adding objects
    private ObservableCollection<Task> tasks = new ObservableCollection<Task>();
    // this will asynchronously iterate through the list of tasks 
    private BackgroundWorker task_worker = new BackgroundWorker();

    public Form1()
    {
        InitializeComponent();
        // set up the event handlers
        tasks.CollectionChanged += tasks_CollectionChanged;
        task_worker.DoWork += task_worker_DoWork;
        task_worker.RunWorkerCompleted += task_worker_RunWorkerCompleted;
        task_worker.WorkerSupportsCancellation = true;

    }

    // ----------- worker events
    void task_worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        if (tasks.Count != 0)
        {
            task_worker.RunWorkerAsync();
        }
    }

    void task_worker_DoWork(object sender, DoWorkEventArgs e)
    {
        try
        {

            foreach (Task t in tasks)
            {
                t.RunSynchronously();
                tasks.Remove(t);
            }
        }
        catch
        {
            task_worker.CancelAsync();
        }
    }


    // ------------- task event
    // runs when a task is added to the list
    void tasks_CollectionChanged(object sender,
        System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
    {
        if (!task_worker.IsBusy)
        {
            task_worker.RunWorkerAsync();
        }
    }

现在您所需要做的就是创建一个新任务并将其添加到列表中。它将由工作人员按照其放入 List<> 的顺序运行。

Task t = new Task(() => {

        // do something here
    });

    tasks.Add(t);

I used Tasks with a BackgroundWorker

You can create any number of tasks and add them to a list of tasks.
The worker will start when a task is added, restart if a task is added while the worker IsBusy, and stop once there are no more tasks.

This will allow you to update the GUI asynchronously as much as you need to without freezing it.

This works as is for me.

    // 'tasks' is simply List<Task> that includes events for adding objects
    private ObservableCollection<Task> tasks = new ObservableCollection<Task>();
    // this will asynchronously iterate through the list of tasks 
    private BackgroundWorker task_worker = new BackgroundWorker();

    public Form1()
    {
        InitializeComponent();
        // set up the event handlers
        tasks.CollectionChanged += tasks_CollectionChanged;
        task_worker.DoWork += task_worker_DoWork;
        task_worker.RunWorkerCompleted += task_worker_RunWorkerCompleted;
        task_worker.WorkerSupportsCancellation = true;

    }

    // ----------- worker events
    void task_worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        if (tasks.Count != 0)
        {
            task_worker.RunWorkerAsync();
        }
    }

    void task_worker_DoWork(object sender, DoWorkEventArgs e)
    {
        try
        {

            foreach (Task t in tasks)
            {
                t.RunSynchronously();
                tasks.Remove(t);
            }
        }
        catch
        {
            task_worker.CancelAsync();
        }
    }


    // ------------- task event
    // runs when a task is added to the list
    void tasks_CollectionChanged(object sender,
        System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
    {
        if (!task_worker.IsBusy)
        {
            task_worker.RunWorkerAsync();
        }
    }

Now all you need is to create a new Task and add it to the List<>. It will be run by the worker in the order it was placed into the List<>

Task t = new Task(() => {

        // do something here
    });

    tasks.Add(t);
俏︾媚 2024-08-10 03:54:06

OpenCV 中存在函数 WaitKey。 Ir 允许以这种方式解决这个问题:

while (this->backgroundWorker1->IsBusy) {
    waitKey(10);
    std::cout << "Wait for background process: " << std::endl;
}
this->backgroundWorker1->RunWorkerAsync();

In OpenCV exists function WaitKey. Ir allows solve this issue in that way:

while (this->backgroundWorker1->IsBusy) {
    waitKey(10);
    std::cout << "Wait for background process: " << std::endl;
}
this->backgroundWorker1->RunWorkerAsync();
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文