我有一个服务负责许多任务,其中一个是在一个单独的线程(threadJob子)上启动作业(一次一个),这些作业可能需要相当长的时间和
有各种各样的阶段,我需要报告.
通常,调用应用程序从服务请求状态(GetStatus),这意味着服务需要知道什么时候作业(子线程)是
在,我希望在某些里程碑,子线程可以某种方式通知(SetStatus)其状态的父线程(服务),并且服务可以返回该信息
到调用应用程序.
例如 - 我希望做这样的事情:
class Service
{
private Thread threadJob;
private int JOB_STATUS;
public Service()
{
JOB_STATUS = "IDLE";
}
public void RunTask()
{
threadJob = new Thread(new ThreadStart(PerformWork));
threadJob.IsBackground = true;
threadJob.Start();
}
public void PerformWork()
{
SetStatus("STARTING");
// do some work //
SetStatus("PHASE I");
// do some work //
SetStatus("PHASE II");
// do some work //
SetStatus("PHASE III");
// do some work //
SetStatus("FINISHED");
}
private void SetStatus(int status)
{
JOB_STATUS = status;
}
public string GetStatus()
{
return JOB_STATUS;
}
};
Run Code Online (Sandbox Code Playgroud)
因此,当需要执行作业时,将调用RunTask()并启动线程(threadJob).这将运行并执行一些步骤(使用SetStatus将新状态设置为
各种要点),最后完成.现在,还有函数GetStatus(),它应该在需要时返回STATUS(来自使用IPC的调用应用程序) - 这个状态
应该反映threadJob运行的作业的当前状态.
所以,我的问题很简单...... threadJob(或者更具体地说是PerformWork())如何以线程安全的方式返回Service状态的变化(我假设我上面的SetStatus/GetStatus示例是
不安全的)?我需要使用活动吗?我假设我不能直接改变JOB_STATUS ...我应该使用LOCK(如果是这样的话?)......
您可以在 Service 类中创建一个事件,然后以线程安全的方式调用它。请密切注意我是如何实现 SetStatus 方法的。
class Service
{
public delegate void JobStatusChangeHandler(string status);
// Event add/remove auto implemented code is already thread-safe.
public event JobStatusChangeHandler JobStatusChange;
public void PerformWork()
{
SetStatus("STARTING");
// stuff
SetStatus("FINISHED");
}
private void SetStatus(string status)
{
JobStatusChangeHandler snapshot;
lock (this)
{
// Get a snapshot of the invocation list for the event handler.
snapshot = JobStatusChange;
}
// This is threadsafe because multicast delegates are immutable.
// If you did not extract the invocation list into a local variable then
// the event may have all delegates removed after the check for null which
// which would result in a NullReferenceException when you attempt to invoke
// it.
if (snapshot != null)
{
snapshot(status);
}
}
}
Run Code Online (Sandbox Code Playgroud)