Я пытаюсь работать с 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" в чистом виде.
Возможно ли это или есть лучшее решение для этого? Спасибо за ваши идеи.
(Я не тестировал код - просто написал это из головы)
Вы вызываете метод stop так же, как вы вызвали метод start:
party.StopParty();
Чтобы гарантировать, что изменения, сделанные в другом потоке, не просто кэшируются, поле partytime
должно быть также отмечено как volatile
.
Вы должны использовать средства синхронизации, такие как 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();
}
}
Он потокобезопасен и подходит не только для этого, но и для более сложных сценариев, а также для работы с задачами.
Если вы хотите, чтобы больше потоков запрашивало одну и ту же переменную, позаботьтесь о проблемах синхронизации нити (когда два потока пытаются получить доступ к одной и той же переменной).
Я собираюсь показать самый безопасный способ (может быть, больше, чем вам нужно). Лучшим способом сделать это является объявление статического объекта для установки 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
гарантирует, что вы делаете правильный путь.