C # Установить переменную в потоке

1

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

Можно ли установить переменную в другом потоке?

Вот небольшой пример кода, чтобы показать вам, что я пытаюсь сделать:

public class PartyClass
{
     public boolean partytime = true;

     public void MakeParty()
     {
          while(partytime)
               Console.WriteLine("I'm making a party here");

          Console.WriteLine("The party ended. Please leave now");
     }

     public void StopParty()
     {
          partytime = false;
     }
}

public class MainThread
{
     public static int Main(String[] args)
     {
          PartyClass party = new PartyClass();
          Thread partyThread = new Thread(new ThreadStart(party.MakeParty()));
          partyThread.Start();
          while (!partyThread.IsAlive) ;

          System.Threading.Thread.Sleep(5000);

          // Now I want to somehow call the StopParty() Method
     }
}

Я не знаю, действительно ли это глупо, что я пытаюсь сделать, но я думаю, что это отличный способ остановить "Partythread" в чистом виде.

Возможно ли это или есть лучшее решение для этого? Спасибо за ваши идеи.

(Я не тестировал код - просто написал это из головы)

  • 1
    Ваш основной поток ожидает остановки второго потока, и второй поток не остановится, пока основной поток не сообщит об этом. Так будет продолжаться вечно.
Теги:
multithreading
network-programming
threadpool

3 ответа

1
Лучший ответ

Вы вызываете метод stop так же, как вы вызвали метод start:

party.StopParty();

Чтобы гарантировать, что изменения, сделанные в другом потоке, не просто кэшируются, поле partytime должно быть также отмечено как volatile.

  • 0
    Нравится? 'volatile bool partytime = true;' Не знал, что я могу вызывать методы в других темах oO: D
  • 0
    @ greece57 Потоки не имеют собственных методов, объектов или памяти (ну, технически, есть память, специфичная для потока, но вам нужно приложить все усилия, чтобы создать ее). Метод не принадлежит ни одному потоку, разные потоки просто обращаются к методам или памяти, которые доступны глобально.
1

Вы должны использовать средства синхронизации, такие как CancellationToken.

Ваш код будет выглядеть так:

public class PartyClass
{
    private readonly CancellationToken _cancellationToken;

    public PartyClass(CancellationToken cancellationToken)
    {
        _cancellationToken = cancellationToken;
    }

    public void MakeParty()
    {
        while (!_cancellationToken.IsCancellationRequested)
            Console.WriteLine("I'm making a party here");

        Console.WriteLine("The party ended. Please leave now");
    }
}

public class MainThread
{
    public static int Main(String[] args)
    {
        var cancellationSource = new CancellationTokenSource();
        PartyClass party = new PartyClass(cancellationSource.Token);
        Thread partyThread = new Thread(party.MakeParty);
        partyThread.Start();

        System.Threading.Thread.Sleep(5000);

        cancellationSource.Cancel();

        partyThread.Join();
    }
}

Он потокобезопасен и подходит не только для этого, но и для более сложных сценариев, а также для работы с задачами.

  • 0
    Могу ли я использовать этот токен также для нескольких потоков и отменить их все, установив один токен? Спасибо за ответ!
  • 0
    Да, просто направьте один и тот же токен (фактически, копии, потому что это структура) на каждый поток, который вы хотите отменить. Больше здесь .
0

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

Я собираюсь показать самый безопасный способ (может быть, больше, чем вам нужно). Лучшим способом сделать это является объявление статического объекта для установки lock, чтобы убедиться, что у вас есть один поток, изменяющий флаг участника сразу.

public class PartyClass
{

    private object _partyTimeLock = new Object();  // executed at class init
    private boolean partyTime= true;

    public bool IsPartyGoingOn()
    {
       bool itIsGoingOn = false;
       lock(_partyTimeLock) {
          itIsGoingOn = partyTime;
       }
       return itIsGoingOn;
    }

    public void StopParty()
    {
        lock(_partyTimeLock) {
           partyTime = false;
        }
    }

    public void MakeParty()
    {
         while(IsPartyGoingOn()) {
              Console.WriteLine("I'm making a party here");
         }

         Console.WriteLine("The party ended. Please leave now");
    }
}

В этом примере здесь, независимо от того, кто пытается вызвать IsPartyGoingOn(), у вас никогда не будет проблемы (независимо от того, является ли это собственным потоком класса или другим). Ключевое слово lock гарантирует, что вы делаете правильный путь.

  • 0
    Блокировка предназначена для синхронизации доступа к общим ресурсам , а не для сигналов между потоками. Если вы хотите использовать «консервативный» API, используйте ManualResetEvent или его * Slim версию.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню