Вы можете использовать Join
или AutoResetEvent
, чтобы дождаться окончания добавления потока изображений, Но вы не должны использовать ни то, ни другое, как объяснено ниже в ответе.
Вы можете достичь тех же результатов, используя AutoResetEvent
в качестве альтернативы Join
; он позволяет настроить уведомление о блокировке, поэтому блокируйте перед вызовом метода execute()
и продолжайте работу только тогда, когда поток AddPics
завершит свою работу:
private AutoResetEvent _finishAddPicsNotifier = new AutoResetEvent(false);
private void OnMyButton_Click(object sender, EventArgs e)
{
//.....
new Thread(AddPics)
{
Priority = ThreadPriority.Highest,
IsBackground = true, //will explain later
}.Start();
_finishAddPicsNotifier.WaitOne();//this will block until receive a signal to proceed
execute();//this method will only be called after the AddPics method finished
/.....
}
private void AddPics()
{
try{
//.......
}
finally{
_finishAddPicsNotifier.Set();//when finished adding the pictures, allow the waiting method to proceed
}
}
Примечание: Установите IsBackground = true
, чтобы указать, что поток является фоновым потоком, поэтому он не будет препятствовать завершению приложения. подробнее о фоновой теме здесь .
Проблемы:
- Поскольку вы используете нажатие кнопки для запуска потока, вы должны добавить некоторый механизм, предотвращающий одновременное многократное нажатие кнопки для многократного выполнения кода.
- Вы также блокируете поток пользовательского интерфейса при вызове
Join()
или _finishAddPicsNotifier.WaitOne()
.
Чтобы исправить все это , хороший дизайн - определить метод OnFinishAddingPictures
и вызывать его всякий раз, когда завершается добавление изображений, внутри этого нового вызова метода execute()
вы также должны удалить предыдущий execute()
звонок от нажатия кнопки:
private readonly object _oneAddPicturesLocker = new object();
private void OnMyButton_Click(object sender, EventArgs e)
{
//.....
new Thread(AddPics)
{
Priority = ThreadPriority.Highest,
IsBackground = true,
}.Start();
}
private void AddPics()
{
if (Monitor.TryEnter(_oneAddPicturesLocker))
{
//we only can proceed if no other AddPics are running.
try
{
//.....
OnFinishAddingPictures();
}
finally
{
Monitor.Exit(_oneAddPicturesLocker);
}
}
}
private void OnFinishAddingPictures()
{
execute();
}
Примечание:
- С помощью этого механизма мы избавляемся от блокировки.
- Мы уверены, что один и только один вызов
AddPics
выполняется в данный момент.
- Всегда не забывайте проверять
InvokeRequired
и использовать control.Invoke(/*..*/)
при каждом обращении к форме или методам управления и свойствам из потока, который не является потоком пользовательского интерфейса .