#c# #.net #wpf #multithreading #thread-safety
#c# #.net #wpf #многопоточность #потокобезопасность
Вопрос:
Я пишу приложение WPF с использованием C #, и мне нужна некоторая помощь с обработкой потоков. У меня есть три класса, каждый из которых должен запускать задачу каждые n секунд в своем собственном потоке. Вот как я это сделал с Qt4:
class myThread : public QThread
{
void run (void)
{
while (true)
{
mMutex.lock();
mWaitCondition.wait (amp;mMutex);
// Some task
mMutex.unlock();
}
}
void wait (int timeout)
{
// For shutdown purposes
if (mMutex.tryLock (timeout))
mMutex.unlock();
}
void wake (void)
{
mWaitCondition.wakeAll();
}
}
// Some other class has a timer which ticks
// every n seconds calling the wake function
// of the myThread class.
Что я получаю от этого, так это контролируемый интервал обновления. Итак, если я обновляю 60 раз в секунду, если код медленный и может выполняться только 30 раз в секунду, у него нет проблем с этим, но он никогда не будет выполняться более 60 раз в секунду. Он также не будет запускать один и тот же код более одного раза одновременно. Какой самый простой способ реализовать это на C #?
Ответ №1:
Вместо этого вам следует использовать Timer
.
Прочитайте эту статью для получения подробной информации или эту для более компактного объяснения.
Ответ №2:
.NET Reactive Extensions допускают сложную асинхронную композицию событий на основе времени — это, вероятно, хорошая отправная точка для поведения, связанного со временем.
Ответ №3:
Вы можете использовать там классы для этого
using System;
using System.Timers;
using System.Threading;
public class ClassTask
{
System.Timers.Timer timer = null;
public bool IsRunning { get; set; }
public DateTime LastRunTime { get; set; }
public bool IsLastRunSuccessful { get; set; }
public double Interval { get; set; }
public bool Stopped { get; set; }
public ClassTask(double interval)
{
this.Interval = interval;
this.Stopped = false;
timer = new System.Timers.Timer(this.Interval);
timer.Elapsed = new ElapsedEventHandler(timer_Elapsed);
timer.Enabled = true;
}
public void Start()
{
this.Stopped = false;
this.StartTask();
}
public void Stop()
{
this.Stopped = true;
}
private void StartTask()
{
if (!this.Stopped)
{
//Thread thread = new Thread(new ThreadStart(Execute));
//thread.Start();
Execute();
}
}
private void Execute()
{
try
{
this.IsRunning = true;
this.LastRunTime = DateTime.Now;
// Write code here
this.IsLastRunSuccessful = true;
}
catch
{
this.IsLastRunSuccessful = false;
}
finally
{
this.IsRunning = false;
}
}
void timer_Elapsed(object sender, ElapsedEventArgs e)
{
if (!this.IsRunning)
StartTask();
}
}
using System;
using System.Data;
using System.Configuration;
public class ClassTaskScheduler
{
ClassTask task = null;
public ClassTaskScheduler()
{
this.task = new ClassTask(60000);
}
public void StartTask()
{
this.task.Start();
}
public void StopTask()
{
this.task.Stop();
}
}
В global.asax или где вы хотите вызвать это
void Application_Start(object sender, EventArgs e)
{
// Code that runs on application startup
ClassTaskScheduler _scheduler = new ClassTaskScheduler();
_scheduler.StartTask();
}
void Application_End(object sender, EventArgs e)
{
// Code that runs on application shutdown
ClassTaskScheduler _scheduler = new ClassTaskScheduler();
_scheduler.StopTask();
}
Вы можете использовать функцию Execute() для выполнения задачи в заданный интервал времени….
Ответ №4:
Эквивалентом в .NET было бы использование ManualResetEvent
. Используйте WaitOne
метод с таймаутом, чтобы вызвать ожидание. Это также может использоваться в качестве механизма завершения работы. Самое приятное в этом подходе то, что он прост, все выполняется одним потоком, и один и тот же код не может выполняться параллельно (потому что все это в одном потоке).
class myThread
{
private ManualResetEvent m_WaitHandle = new ManualResetEvent(false);
public myThread
{
new Thread(Run).Start();
}
public void Shutdown()
{
m_WaitHandle.Set(); // Signal the wait handle.
}
private void Run()
{
while (!m_WaitHandle.WaitOne(INTERVAL)) // The waiting happens here.
{
// Some task
}
// If execution gets here then the wait handle was signaled from the Shutdown method.
}
}