在C#.NET,我已经写了下面的简单的背景工作者线程:
public class MyBackgrounder
{
public delegate void dlgAlert();
public dlgAlert Alert;
public event EventHandler eventAlert;
Thread trd;
public void Start()
{
if (trd == null || trd.ThreadState == ThreadState.Aborted)
{
trd = new Thread(new ThreadStart(Do));
}
trd.IsBackground = true;
trd.Priority = ThreadPriority.BelowNormal;
trd.Start();
}
void Do()
{
Thread.Sleep(3000);
Done();
}
void Done()
{
if (Alert != null)
Alert();
if (eventAlert != null)
eventAlert(this, new EventArgs());
Kill();
}
public void Kill()
{
if (trd != null)
trd.Abort();
trd = null;
}
}
static class Program
{
[STAThread]
static void Main()
{
MyBackgrounder bg = new MyBackgrounder();
bg.eventAlert += new EventHandler(bg_eventAlert);
bg.Alert = jobDone;
bg.Start();
}
static void bg_eventAlert(object sender, EventArgs e)
{
// here, current thread's id has been changed
}
static void jobDone()
{
// here, current thread's id has been changed
}
}
它只是等待3秒(它的工作),然后引发指定事件或调用的委托。 有没有问题,直到这里,一切工作正常。 但是,当我看“Thread.CurrentThread.ManagedThreadId”,我看到它的后台线程! 也许这是正常的,但我怎样才能防止这种行为? 如果测试“System.Windows.Forms.Timer”组件和处理其“ 蜱 ”的事件,你可以看到“Thread.CurrentThread.ManagedThreadId”尚未从主线程ID改为别的。
我能做什么?
定时器运行在主线程(并将于后期都会响起来,如果主线程是真的很忙)。 如果由于某种原因,你想jobDone()从主线程调用,你可以,例如使用的是内螺纹和具有被称为与主线程线程的一些具体事件的BackgroundWorker对象(允许UI更新等)
到底是什么这是你的后台线程错误? 你描述的,看起来很好,对我来说至今。
该System.Windows.Forms.Timer
你检查比较可能的UI线程 ,这的确将使它在非后台线程上运行。
从的MSDN文档Thread.IsBackground属性(由我亮点):
线程可以是一个背景线程或前台线程。 后台线程是相同的前景线程,所不同的是后台线程不会阻止从终止进程。 一旦属于一个进程的所有前台线程已经终止,公共语言运行时结束处理。 任何剩余的后台线程停止并没有完成。
这个怎么样设计:
创建表单的的EventWaitHandle对象。
private EventWaitHandle layer2changed = new EventWaitHandle(false, EventResetMode.ManualReset);
在定时器事件处理程序执行以下操作:
if (this.layer2changed.WaitOne(0, false)) { // perform UI updates according to some public properties of layer1/layer2 this.layer2changed.Reset(); }
传递给layer2changed到层1 /层等在它们的构造函数的引用。
每次你做()方法做一些事情,需要更新UI信号的事件:
this.referencedLayer2Changed.Set();
但是请注意,这将有二层和UI的变化(时间越长Form.Timer间隔 - 越长越差)之间的时间差。
注意给大家:这是一个负全部的解决方案由losingsleep在评论他的问题指定的附加要求不断涌现。 请阅读他们downvoting之前。 :-)
我觉得有这并不需要在底层(二层)“System.Windows.Forms的”参照另一种解决方案:
第一层(UI形式)提供了一个超时的实现,二层可以使用。
有一个接口:
namespace Layer2
{
public delegate void TimeoutAlert();
public interface IApplicationContext
{
void SetTimeout(TimeoutAlert timeoutAlerthandler, int milliseconds);
}
}
在二层工作类:
namespace Layer2
{
public class Worker
{
IApplicationContext _context;
public void DoJob(IApplicationContext context)
{
_context = context;
_context.SetTimeout(JobTimedOut,3000);
// nothing ... (wait for other devices or user events)
}
void JobTimedOut()
{
// do something suitable for timeout error with _context or anything else
}
}
}
在UI,我们有这样的:
using Layer2;
namespace Layer1
{
public partial class frmTest : Form, IApplicationContext
{
int timeout;
TimeoutAlert _timeoutAlerthandler;
public frmTest()
{
InitializeComponent();
}
private void frmTest_Load(object sender, EventArgs e)
{
Worker w = new Worker();
w.DoJob(this);
}
private void timer1_Tick(object sender, EventArgs e)
{
// it's the handler of 'Timer' component named 'timer1'
timer1.Enabled = false;
if (_timeoutAlerthandler != null)
_timeoutAlerthandler();
}
#region IApplicationContext Members
void IApplicationContext.SetTimeout(TimeoutAlert timeoutAlerthandler, int milliseconds)
{
_timeoutAlerthandler = timeoutAlerthandler;
timeout = milliseconds;
timer1.Interval = milliseconds;
timer1.Enabled = true;
}
#endregion
}
}
我又发现我的情况:
我有一个使用一个核心项目(二层)做一些工作Windows应用程序项目(层)。 核心需求中的一些方法无阻塞超时检查,而无需创建一个不同的线程,导致超时后需要再次与UI交互。 对不起,如果我无法用语言形容了,因为它是一个有点复杂(我!)。