Compact Framework, Windows Mobile 6, C #.
Я собираюсь попробовать некоторые фоновые потоки на компактной платформе и у меня возник вопрос: прекратить рабочий поток.
Код
У меня есть следующий класс ThreadWorker (код из здесь ), который при выполнении будет выполнять проверку в определенных точках, чтобы определить, должен ли он выйти или нет .....
public class ThreadWorker
{
public event EventHandler<ProgressEventArgs> OnProgress;
protected virtual void Progress(ProgressEventArgs args)
{
if (OnProgress != null)
OnProgress(this, args);
}
private void DoLongProcess()
{
// This will take a long time.
Thread.Sleep(15000);
Progress(new ProgressEventArgs("Some info for the UI to display."));
Thread.Sleep(15000);
}
public void DoSomeBackgroundWork()
{
try
{
while (!Stopping)
{
DoLongProcess();
if (Stopping) return;
DoLongProcess();
if (Stopping) return;
DoLongProcess();
if (Stopping) return;
DoLongProcess();
if (Stopping) return;
}
}
finally
{
SetStopped();
}
Console.WriteLine("DoSomeBackgroundWork: Terminating gracefully.");
}
/// <summary>
/// Lock covering stopping and stopped
/// </summary>
readonly object locker = new object();
/// <summary>
/// Whether or not the worker thread has been asked to stop
/// </summary>
bool stopping = false;
/// <summary>
/// Whether or not the worker thread has stopped
/// </summary>
bool stopped = false;
/// <summary>
/// Returns whether the worker thread has been asked to stop.
/// This continues to return true even after the thread has stopped.
/// </summary>
public bool Stopping
{
get
{
lock (locker)
{
return stopping;
}
}
}
/// <summary>
/// Returns whether the worker thread has stopped.
/// </summary>
public bool Stopped
{
get
{
lock (locker)
{
return stopped;
}
}
}
/// <summary>
/// Tells the worker thread to stop, typically after completing its
/// current work item. (The thread is *not* guaranteed to have stopped
/// by the time this method returns.)
/// </summary>
public void Stop()
{
lock (locker)
{
stopping = true;
}
}
/// <summary>
/// Called by the worker thread to indicate when it has stopped.
/// </summary>
void SetStopped()
{
lock (locker)
{
stopped = true;
}
}
}
... и следующая форма инициирует поток ...
public partial class Test : Form
{
public Test()
{
InitializeComponent();
}
private ThreadWorker myThreadWorker;
private Thread t = null;
private void Test_Load(object sender, EventArgs e)
{
myThreadWorker = new ThreadWorker();
myThreadWorker.OnProgress += new EventHandler<ProgressEventArgs>(myThreadWorker_OnProgress);
}
private void miStart_Click(object sender, EventArgs e)
{
try
{
listResults.Items.Insert(0, "Set-up Thread.");
t = new Thread(myThreadWorker.DoSomeBackgroundWork);
t.Name = "My Thread";
t.Priority = ThreadPriority.BelowNormal;
t.Start();
listResults.Items.Insert(0, "Thread started.");
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
private void miStop_Click(object sender, EventArgs e)
{
try
{
listResults.Items.Insert(0, "Waiting for My Thread to terminate.");
listResults.Refresh();
myThreadWorker.Stop();
t.Join();
listResults.Items.Insert(0, "My Thread Finished.");
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
private delegate void InsertToListBoxDelegate(String text);
private void InsertToListBox(String text)
{
if (InvokeRequired)
Invoke(new InsertToListBoxDelegate(InsertToListBox), new object[] { text });
else
{
listResults.Items.Insert(0, "{0}".With(text));
listResults.Refresh();
}
}
void myThreadWorker_OnProgress(object sender, ProgressEventArgs e)
{
InsertToListBox(e.Text);
}
}
Проблема
Когда я нажимаю кнопку Стоп, она вызывает ...
myThreadWorker.Stop();
t.Join();
listResults.Items.Insert(0, "My Thread Finished.");
... я ожидал, что ThreadWorker продолжит работу с текущим DoLongProcess () до его завершения и будет по-прежнему вызывать событие в пользовательском интерфейсе через обработчик событий OnProgress и myThreadWorker_OnProgress.
Однако на самом деле происходит, когда OnProgress вызывается, приложение останавливается при чтении строки ...
Invoke(new InsertToListBoxDelegate(InsertToListBox), new object[] { text });
Вопрос
Как мне позвонить ...
myThreadWorker.Stop();
t.Join();
... и по-прежнему отвечать на события из фонового потока, пока он не завершится?