Как я могу синхронизировать эти потоки, чтобы избежать повреждения данных? - PullRequest
2 голосов
/ 16 февраля 2009

TL; DR версия: у меня две темы. Одному из них может потребоваться Interrupt () другого, но только если другой поток находится в середине обработки данных, связанных с объектом, на который влияет первый поток. Как я могу только прервать () второй поток на основе определенных условий.

Я работал над программой, которая раскручивает два потока для обработки данных сокета и обновления графического интерфейса с информацией. Два потока (topologyThread и dataThread) обрабатывают два различных аспекта моего приложения, а именно уведомления об изменении топологии для нашей беспроводной сенсорной сети и информацию о данных для получения и обработки данных из беспроводной сенсорной сети.

Когда данные поступают в dataThread, возможно, что член сети, который представляет пакет данных, уже был удален topologyThread и поэтому не должен обрабатываться. Итак, я подумал, что использование метода Thread.Interrupt () позволило бы мне мгновенно уведомить dataThread об изменениях в топологии и предотвратить некоторые проблемы, с которыми мы столкнулись при попытке обновить графический интерфейс пользователя данными для члена сети, который является больше не подключен. У меня такой вопрос: как я могу определить, нужно ли прерывать dataThread? Я не хочу, чтобы он выдавал исключение во время обработки данных для члена сети, который все еще подключен, но я хочу, чтобы он прерывался, если он находится в середине обработки данных для члена сети, который затем отключается.

Сценарий 1:

  • Данные поступают на dataThread.
  • dataThread гарантирует, что член сети по-прежнему является частью сети.
  • dataThread обрабатывает данные до конца и обновляет графический интерфейс

Сценарий 2:

  • Данные поступают на dataThread.
  • dataThread гарантирует, что член сети по-прежнему является частью сети.
  • Участник сети отключен, поэтому обработка не производится.

Сценарий 3:

  • Данные поступают на dataThread.
  • dataThread гарантирует, что член сети по-прежнему является частью сети.
  • dataThread начинает обработку данных
  • topologyThread получает уведомление о том, что участник сети отключен, и удаляет его из топологии.
  • dataThread пытается обновить графический интерфейс для участника сети, который больше не подключен.

Это сценарий 3, для которого я пытаюсь написать код. В нашем тестировании в этом сценарии древовидное представление на боковой панели зависает и приложение должно быть убито. Но мне нужно прервать dataThread только в том случае, если объект, на который влияет topologyThread, является объектом, на который в данный момент действует dataThread.

Спасибо за чтение. :)

Ответы [ 4 ]

2 голосов
/ 16 февраля 2009

Вы не должны прерывать ваши темы. Возможно, было бы безопаснее запрограммировать их, используя EventWaitHandles, которые могли бы генерировать сигналы, основанные на том, чего вы пытаетесь достичь.

1 голос
/ 16 февраля 2009

dataThread пытается обновить графический интерфейс для участника сети, который больше не подключен.

Что если у вас есть topologyThread, установивший флаг, когда член сети больше не подключен, и у dataThread проверяют этот флаг перед попыткой обновить графический интерфейс?

0 голосов
/ 16 февраля 2009

Базовая версия. Улучшение в соответствии с вашими потребностями.

public class CancellationInfo {
    bool _Cancel = false;
    bool _Sync = new object();
    public bool Requested { get { lock(_Sync) { return _Cancel; } }
    public void Request() { lock(_Sync) _Cancel = true; }
}

public class ThreadActions {
    private CancellationInfo Cancel = new CancellationInfo;
    public void FirstThreadAction() {
        while(true) {
            //Process some stuff.
            if(condition)
               Cancel.Request();
        }
    }
    public SecondThreadAction() {
        while(true) {
            if(Cancel.Requested)
                break;
            //Process some stuff.
        }
    }
}
0 голосов
/ 16 февраля 2009

Interrupt () работает только в том случае, если поток заблокирован ... поэтому вам нужен другой механизм для остановки обработки. Если у вас есть цикл обработки данных, лучше всего иметь переменную, которая прекратит обработку, если она установлена.

Вот как бы я это сделал ...

Thread dataThread;
bool continueProcessing = true;
String currentNetworkMember = "";

public NotifyMemberRemoved(String member)
{
   if (currentNetworkMember == member)
   {
         continueProcessing = false;
         // Incase the thread is blocked...
         dataThread.Interrupt();
   }
}

public void ProcessingLoop()
{
    while (true)
    {
        currentNetworkMember = GetMemberToProcess();
        continueProcessing = true;
        while (continueProcessing)
        {
            try 
            {
               // Process data...
               ReadDataChunk();
               ProcessDataChunk();
            }
            catch (InterruptedException e)
            {
               // Whatever interrupted us must have set continueProcessing to false...
            }
        }
        UpdateGUI();
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...