for k,v in kwarg.iteritems():
setattr(self, k, v)
В котором setattr(self, "bin", "val")
похоже на вызов self.bin = "val"
Однако более желательно иметь белый список, как у @Sven Marnach.
Существует примитив потоковой передачи, ManualResetEvent
, который выполняет именно эту задачу - вы не хотите использовать логический флаг.
Что-то вроде этого должно выполнять job:
public void MyTest()
{
var doneEvent = new ManualResetEvent(false);
myEventRaiser.OnEvent += delegate { doStuff(); doneEvent.Set(); };
myEventRaiser.RaiseEventInSeparateThread();
doneEvent.WaitOne();
Assert.That(stuff);
}
Что касается отсутствия поддержки ключевого слова volatile
в локальных переменных, я не думаю, что есть какая-либо причина, по которой это может быть теоретически невозможным в C #. Скорее всего, он не поддерживается просто потому, что до C # 2.0 такая функция не использовалась. Теперь, когда существуют анонимные методы и лямбда-функции, такая поддержка потенциально может стать полезной. Кто-нибудь, пожалуйста, проясните, если мне что-то здесь не хватает.
Что произойдет, если возникшее событие не завершится до тех пор, пока процесс не выйдет из области действия этой локальной переменной? Переменная была бы освобождена, и ваш поток завершился бы ошибкой.
Разумный подход состоит в том, чтобы присоединить функцию делегата, которая указывает родительскому потоку, что подпоток завершился.
В большинстве сценариев локальные переменные относятся к потоку, поэтому проблемы, связанные с volatile
, совершенно не нужны.
Это меняется, когда как и в вашем примере, это «захваченная» переменная - когда она незаметно реализована как поле в классе, созданном компилятором. Так что теоретически он может быть нестабильным, но в большинстве случаев это не стоит дополнительных сложностей.
В частности, что-то вроде Monitor
(также известного как lock
) с Pulse
и т. Д. Могут сделать это так же хорошо, как и любое количество других конструкций потоков.
Распределение потоков сложно, и активный цикл редко является лучшим способом управления им. .
Повторное редактирование ... secondThread. Join ()
было бы очевидным, но если вы действительно хотите использовать отдельный токен, см. Ниже. Преимущество этого (по сравнению с такими вещами, как ManualResetEvent
) заключается в том, что он не требует ничего от ОС - он обрабатывается исключительно внутри интерфейса командной строки.
using System;
using System.Threading;
static class Program {
static void WriteLine(string message) {
Console.WriteLine(Thread.CurrentThread.Name + ": " + message);
}
static void Main() {
Thread.CurrentThread.Name = "Main";
object syncLock = new object();
Thread thread = new Thread(DoStuff);
thread.Name = "DoStuff";
lock (syncLock) {
WriteLine("starting second thread");
thread.Start(syncLock);
Monitor.Wait(syncLock);
}
WriteLine("exiting");
}
static void DoStuff(object lockHandle) {
WriteLine("entered");
for (int i = 0; i < 10; i++) {
Thread.Sleep(500);
WriteLine("working...");
}
lock (lockHandle) {
Monitor.Pulse(lockHandle);
}
WriteLine("exiting");
}
}