使用后台工作者 [英] Using background worker
问题描述
我尝试使用带有invoke方法的单独线程从非GUI线程写入WinForm属性。什么都没有工作后我发现了背景工人,这似乎是一个更容易的解决方案。我找到了一个例子,从Form1程序启动了一个定时器,它会定期调用后台工作器的doWork函数。我创建了一个带有单个标签的表单和一个名为bgw的后台工作程序。我设置了三个中断dowork,进度改变和runworkercompleted。我还将WorkerReportsProgress和WorkerSupports Cancellation设置为True。我复制了代码来自
c# - 使用Timer与Backgroundworker一起确保调用doWork方法 - 代码审查堆栈交换 [ ^ ]
以下是我使用的代码:
使用系统;
使用 System.Collections.Generic;
使用 System.ComponentModel;
使用 System.Data;
使用 System.Drawing;
使用 System.Linq;
使用 System.Text;
使用 System.Threading;
使用 System.Windows.Forms;
命名空间 Background_Worker_Test
{
public partial class Form1:Form
{
// 设置为perioically调用后台工作程序
System.Windows.Forms.Timer tmrCallBgWorker; // 调用Backgroundworker的计时器
// 我们的后台工作者是backgroundWorker1
// 用于确保调用BackgroundWorker的计时器
System.Threading.Timer tmrEnsureWorkerGetsCalled;
// 用于saft访问的对象;
object lockObject = new object ();
public int TestInt;
public Form1()
{
InitializeComponent();
// 此计时器定期调用BackgroudnWorker
tmrCallBgWorker = new System.Windows.Forms.Timer();
tmrCallBgWorker.Tick + = new EventHandler(tmrCallBgWorker_tick);
tmrCallBgWorker.Interval = 1000 ;
bgw.DoWork + = new DoWorkEventHandler(bgw_DoWork);
bgw.RunWorkerCompleted + = new RunWorkerCompletedEventHandler(bgw_RunWorkerCompleted);
}
void tmrCallBgWorker_tick( object sender ,EventArgs e)
{
if (Monitor.TryEnter(lockObject))
{
尝试
{
// 如果bgw不忙如果(!bgw.IsBusy)
bgw.RunWorkerAsync();请致电工人
}
finally
{
Monitor.Exit(lockObject);
}
}
else
{
// 当te bgw忙,启动一个新的计时器,它将调用
// 尝试在一段时间后再次调用bgw
tmrEnsureWorkerGetsCalled = new System.Threading.Timer
( new TimerCallback(tmrEnsureWorkerGetsCalled_Callback), null , 0 , 10 );
}
}
void tmrEnsureWorkerGetsCalled_Callback( object obj)
{
尝试
{
如果 (!bgw.IsBusy)
bgw.RunWorkerAsync();
}
finally
{
Monitor.Exit(lockObject);
}
tmrEnsureWorkerGetsCalled = null ;
}
private void bgw_DoWork( object sender,DoWorkEventArgs e)
{
label1.Text = string .Format( In do work {0:N3} ,TestInt);
}
private void bgw_ProgressChanged( object sender,ProgressChangedEventArgs e)
{
}
private void bgw_RunWorkerCompleted( object sender,RunWorkerCompletedEventArgs e)
{
}
}
}
dode通过Form1()方法和挂起。尽管我可以说它正在继续重新初始化。我是C#的新手,但不知道为什么这不起作用。看起来更直接的是新线程接近调用所需的东西。帮助!
谢谢,
安迪克鲁斯
我尝试过:
开始使用线程方法写入WinForm属性但无法正常工作。转移到使用Backgroud Worker并发现我认为是一个我无法运行的简单示例。
你没有启动计时器......
public Form1()
{
InitializeComponent();
// 此计时器定期调用BackgroudnWorker
tmrCallBgWorker = new System.Windows.Forms.Timer();
tmrCallBgWorker.Tick + = new EventHandler(tmrCallBgWorker_tick);
tmrCallBgWorker.Interval = 1000 ;
bgw.DoWork + = new DoWorkEventHandler(bgw_DoWork);
bgw.RunWorkerCompleted + = new RunWorkerCompletedEventHandler(bgw_RunWorkerCompleted);
}添加以下行:
tmrCallBgWorker.Start();
在此行之后:
tmrCallBgWorker.Interval = 1000 ;
I tried using a separate thread with an invoke method to write to WinForm properties from a non GUI thread. After getting nothing to work I found out about Background Worker which seems to be an easier solution. I found an example that from the Form1 program started a timer that would call the background worker doWork function periodically. I created a form with a single label and a Background Worker called bgw. I setup the three interrupts dowork, progress changed and runworkercompleted. I also set WorkerReportsProgress and WorkerSupports Cancellation to True. I copied the code from
c# - Using Timer with Backgroundworker to ensure the doWork method is called - Code Review Stack Exchange[^]
Here is the code I used:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Windows.Forms;
namespace Background_Worker_Test
{
public partial class Form1 : Form
{
// Setup to call Background worker perioically
System.Windows.Forms.Timer tmrCallBgWorker; // timer to call Backgroundworker
// our Background Worker is backgroundWorker1
// timer to make sure BackgroundWorker Gets Called
System.Threading.Timer tmrEnsureWorkerGetsCalled;
// object used for saft access;
object lockObject = new object();
public int TestInt;
public Form1()
{
InitializeComponent();
// This timer call BackgroudnWorker at regular intervals
tmrCallBgWorker = new System.Windows.Forms.Timer();
tmrCallBgWorker.Tick += new EventHandler(tmrCallBgWorker_tick);
tmrCallBgWorker.Interval = 1000;
bgw.DoWork += new DoWorkEventHandler(bgw_DoWork);
bgw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bgw_RunWorkerCompleted);
}
void tmrCallBgWorker_tick(object sender, EventArgs e)
{
if (Monitor.TryEnter(lockObject))
{
try
{
// if bgw is not busy call the worker
if (!bgw.IsBusy)
bgw.RunWorkerAsync();
}
finally
{
Monitor.Exit(lockObject);
}
}
else
{
// as te bgw is busy, start a new timer that will call
// try to call bgw again after some time
tmrEnsureWorkerGetsCalled = new System.Threading.Timer
(new TimerCallback(tmrEnsureWorkerGetsCalled_Callback), null, 0, 10);
}
}
void tmrEnsureWorkerGetsCalled_Callback(object obj)
{
try
{
if (!bgw.IsBusy)
bgw.RunWorkerAsync();
}
finally
{
Monitor.Exit(lockObject);
}
tmrEnsureWorkerGetsCalled = null;
}
private void bgw_DoWork(object sender, DoWorkEventArgs e)
{
label1.Text = string.Format("In do work {0:N3}", TestInt);
}
private void bgw_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
}
private void bgw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
}
}
}
The dode goes through the Form1() method and the hangs. As near as I can tell it is continuing to reinitialize. I'm new to C# but can't see why this doesn't work. Seems much more straight forward that the new thread approach with the invoke stuff required. HELP!
Thanks,
Andy Cruce
What I have tried:
Started using a thread method to write to WinForm Properties but couldn't get that working. Moved to using Backgroud Worker and found what I thought was a simple example that I can't get to run.
You don't start the timer ...
public Form1() { InitializeComponent(); // This timer call BackgroudnWorker at regular intervals tmrCallBgWorker = new System.Windows.Forms.Timer(); tmrCallBgWorker.Tick += new EventHandler(tmrCallBgWorker_tick); tmrCallBgWorker.Interval = 1000; bgw.DoWork += new DoWorkEventHandler(bgw_DoWork); bgw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bgw_RunWorkerCompleted); }Add this line:
tmrCallBgWorker.Start();
After this line:
tmrCallBgWorker.Interval = 1000;
这篇关于使用后台工作者的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!