【发布时间】:2015-01-14 15:06:03
【问题描述】:
我有一个按钮,当按下该按钮时,可以获取远程 PC 上各种 Windows 服务的状态。我想每分钟自动刷新一次此按钮,以便始终显示服务的最新状态。
我试图设置一个计时器,但我不断收到错误消息“跨线程操作无效:控制 'btnRefreshServices' 从创建它的线程以外的线程访问”
任何帮助表示赞赏
private void btnRefreshServices_Click(
object sender,
EventArgs eventArgs)
{
this.btnRefreshServices.Enabled = false;
// Setting up progress bar in a separate thread to update the progress bar
// This is necessary so that the dialog doesn't freeze while the progress bar is reporting its progress
this.prgbServiceStatus.Minimum = 1;
this.prgbServiceStatus.Maximum = 11;
this.prgbServiceStatus.Step = 1;
this.prgbServiceStatus.Value = 1;
this.prgbServiceStatus.Increment(1);
this.prgbServiceStatus.PerformStep();
var _backgroundWorker = new BackgroundWorker();
_backgroundWorker.ProgressChanged += ProgressChanged;
_backgroundWorker.DoWork += DoWork;
_backgroundWorker.WorkerReportsProgress = true;
_backgroundWorker.RunWorkerAsync();
_backgroundWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(RunWorkerCompleted);
}
private void DoWork(
object sender,
DoWorkEventArgs doWorkEventArgs)
{
// Get the current status of each Windows service and reflect the progress in the progress bar
// NOTE: If you add a new service, divide the number of services by 100 and update each call to report progress
((BackgroundWorker)sender).ReportProgress(15);
CurrentStatus(
this.grdResults,
ServerA,
ServiceName,
RowIndexA);
((BackgroundWorker)sender).ReportProgress(25);
CurrentStatus(
this.grdResults,
ServerB,
ServiceNameB,
RowIndexB);
((BackgroundWorker)sender).ReportProgress(35);
}
我在计时器上使用了类似这样的代码
Timer myTimer = new Timer();
myTimer.Elapsed += new ElapsedEventHandler(DisplayTimeEvent);
myTimer.Interval = 1000; // 1000 ms is one second
myTimer.Start();
public static void DisplayTimeEvent(object source, ElapsedEventArgs e)
{
// code here will run every second
}
使用 Emile Pels 代码,我能够解决我的问题。
public frmServicesManager()
{
InitializeComponent();
// The interval in milliseconds (1000 ms = 1 second)
const double interval = 5000.0;
// Create a new timer
new System.Timers.Timer()
{
Enabled = true,
Interval = interval
}.Elapsed += TimerCallback;
}
private void TimerCallback(
object sender,
ElapsedEventArgs elapsedEventArgs)
{
// SignalTime is now of type DateTime and contains the value indicating when the timer's Elapsed event was raised
var _signalTime = elapsedEventArgs.SignalTime;
// Create a new Action
var _setButtonClick = new Action<DateTime>(dateTime => this.btnRefreshServices.PerformClick());
// Check if we can access the control from this thread
if (this.btnRefreshServices.InvokeRequired)
{
// We can't access the label from this thread,so we'll call invoke so it is executed from the thread the it was created on
this.btnRefreshServices.Invoke(_setButtonClick, _signalTime);
}
}
【问题讨论】:
-
您使用的是哪个 .NET 框架版本?
-
使用版本 4.5.50709
-
任何关于如何编写解决方案的建议都非常感谢
-
@xxbbcc 同意。这是来自工作线程的基本控制访问。
标签: c# multithreading user-interface webforms