Почему? простой, резьба опасно. У него есть умение для не делать то, что вы надеетесь, он будет делать.
Многие классы графического интерфейса в Winforms не являются потокобезопасными, вы должны использовать команду Control.BeginInvoke, чтобы вы изменяли свои свойства или вызывали их методы в том же самом потоке, который создал объекты. Это довольно фундаментальное ограничение, создавая потокобезопасный код: сложно.
Даже простые классы в .NET не являются потокобезопасными, ни один из классов коллекции не является. У вас есть широта с, скажем, списком <>, вы можете сделать его потокобезопасным, тщательно используя ключевое слово lock, чтобы гарантировать, что объект List доступен только из одного потока. Все еще довольно сложно сделать правильно.
Это перестает быть практичным, если класс не прост и имеет нетривиальные взаимодействия с другими классами и операционной системой. Немногие классы в .NET имеют тяжелый контроль, у него сотни методов и свойств.Таким образом, сама Microsoft просто заявила о том, что сделать ее потокобезопасной невозможной, например, со списком <>, и нет никакой надежды на то, что вы можете добавить достаточно блокировки, чтобы сделать ее потокобезопасной. Тупик практически гарантирован. Microsoft также не предоставила вам достаточный доступ к внутренним компонентам, чтобы ввести требуемую блокировку, они не думали, что это того стоит.
Значит, вы должны использовать объекты из одной и той же темы, чтобы обеспечить безопасность, они предоставили вам необходимые инструменты, чтобы сделать это легко. В том числе BeginInvoke и всевозможные дополнительные справки, такие как BackgroundWorker, TaskScheduler.FromCurrentSynchronizationContext и ключевые слова async/await. И InvalidOperationException вы получаете, когда делаете это неправильно, очень полезное исключение.
Специфическая деталь реализации класса Timer, с которым вы столкнулись, состоит в том, что это довольно простой класс, а фактически - это потокобезопасный. Запуск или остановка на рабочем потоке работает отлично, и это безопасно. Обратите внимание, что вы не получили исключение InvalidOperationException, которое вы обычно получаете, когда нарушаете требования к потоку. К сожалению, это зависит от деталей реализации, о которых вы не заботились, и никогда не будет. Событие Tick добавляется в цикле диспетчера, который вы получаете из Application.Run(). И вы не вызывали Application.Run() в своем рабочем потоке. Поэтому таймер никогда не гаснет.
Правильное решение здесь не call Application.Run() для вашего рабочего, это одно решение, которое дает вам две новые проблемы. У вас уже есть отличный поток, который называется Application.Run(). Используйте Control.BeginInvoke(), чтобы использовать его.
Я хорошо читаю код, чем прохождение, большинство из них здесь согласятся со мной! Поэтому отправляйте какой-то код, мы не можем принимать и отвечать. –
Если вы используете 'System.Windows.Forms.Timer', то он будет всегда выполняться только в потоке пользовательского интерфейса. Не уверен, что об этом вы спрашиваете? Таймеры не будут запускаться в потоке, это запущено, я понятия не имею, почему, по вашему мнению, он срабатывает в том же потоке, который начался? –
Запустите свой таймер в потоке пользовательского интерфейса и запустите новый поток в своем Tick-событии, чтобы выполнить опрос. – Koen