Есть сервис
class MainService : ServiceBase
{
event EventHandler MyEvent;
Thread m_Thread = null;
...
protected override void OnStart(string[] args)
{
//тут System.Threading.Thread.CurrentThread.ManagedThreadId = 1
MyEvent += delegate {
//Тут System.Threading.Thread.CurrentThread.ManagedThreadId = 5
};
m_Thread = new Thread(new ThreadStart(MonitorThread));
m_Thread.IsBackground = true;
m_Thread.Start();
}
protected override void OnStop()
{
m_Thread.Abort();
}
...
private void MonitorThread()
{
//Something
MyEvent?.Invoke(this, EventArg.Empty);
//Something
}
...
}
в MonitorThread
иногда вызываются события MyEvent
, естественно вызов происходит в потоке отличного от основного потока, как мне вызвать событие или какой-либо метод по событию в основном потоке???
PS: SynchronizationContext.Current
в сервисе = null
PS2: Сборка в .Net Framework 2.0
Никак, основной поток в вин-службах полностью отведен под управление временем жизни и системные события (OnStart, OnStop и т.п.)
Если вам зачем-то нужен основной поток - надо просто выбрать один из ваших дополнительных потоков и "назначить" его основным.
Если вас не устраивает ваш MonitorThread в качестве такового - держите реализацию потока с очередью сообщений:
class QueueSynchronizationContext : SynchronizationContext, IDisposable
{
private readonly BlockingCollection<WorkItem> queue = new BlockingCollection<WorkItem>();
public override void Post(SendOrPostCallback d, object state)
{
try { queue.Add(new WorkItem(d, state)); }
catch (InvalidOperationException) { if (Debugger.IsAttached) Debugger.Break(); }
// Если уже был вызван CompleteAdding - мы уже не можем добавить элемент в очередь, но и позволять службе падать также не стоит
// (нет ничего глупее чем программа которая падает при закрытии). Поэтому лучшее что тут можно сделать - это забыть.
}
public override void Send(SendOrPostCallback d, object state)
{
try
{
using (var e = new ManualResetEvent(initialState: false))
{
queue.Add(new WorkItem(d, state, e));
e.WaitOne();
}
}
catch (InvalidOperationException) { if (Debugger.IsAttached) Debugger.Break(); }
// Если уже был вызван CompleteAdding - мы уже не можем добавить элемент в очередь, но и позволять службе падать также не стоит
// (нет ничего глупее чем программа которая падает при закрытии). Поэтому лучшее что тут можно сделать - это забыть.
}
public bool ProcessQueue(CancellationToken token)
{
try
{
foreach (var wi in queue.GetConsumingEnumerable(token))
wi.Execute();
return true;
}
catch (OperationCanceledException) { return false; }
}
public void Complete() => queue.CompleteAdding();
public void Dispose() => queue.Dispose();
private class WorkItem
{
private SendOrPostCallback d;
private object state;
private ManualResetEvent e;
public WorkItem(SendOrPostCallback d, object state, ManualResetEvent e = null)
{
this.d = d;
this.state = state;
this.e = e;
}
public void Execute()
{
try { d(state); }
finally { e?.Set(); }
}
}
}
class MyService : ServiceBase
{
private QueueSynchronizationContext ctx;
private Thread mainThread;
protected override void OnStart(string[] args)
{
this.ctx = new QueueSynchronizationContext();
this.mainThread = new Thread(MainThread);
this.mainThread.Start();
}
protected override void OnStop()
{
// Не забыть отменить фоновые задачи и дождаться их завершения
// ПЕРЕД вызовом ctx.Complete()!
ctx.Complete();
mainThread.Join();
ctx.Dispose();
}
private void MainThread()
{
SynchronizationContext.SetSynchronizationContext(ctx);
ctx.ProcessQueue(CancellationToken.None);
}
}
Кофе для программистов: как напиток влияет на продуктивность кодеров?
Рекламные вывески: как привлечь внимание и увеличить продажи
Стратегії та тренди в SMM - Технології, що формують майбутнє сьогодні
Выделенный сервер, что это, для чего нужен и какие характеристики важны?
Современные решения для бизнеса: как облачные и виртуальные технологии меняют рынок
Вот мне стало интересно, влияют ли переменные пустые на работу кода?
Есть модель новостей, там коллекция картинок (их несколько штук для каждой новости)Надо вывести только первую картинку из этой коллекции