#wpf #vb.net #backgroundworker #dispatchertimer
#wpf #vb.net #фоновый рабочий #dispatchertimer
Вопрос:
Я пытаюсь найти наилучший способ подойти к этому вопросу.
У меня есть BackgroundWorker, который используется для подключения сокета по таймеру.
Public Shared AllUsersWorker As New BackgroundWorker
Public Shared AllUsersWorkerTimer As New DispatcherTimer
AllUsersWorkerTimer.Interval = TimeSpan.FromSeconds(2)
AllUsersWorkerTimer.Start()
AddHandler AllUsersWorkerTimer.Tick, AddressOf All_Users_Worker_Timer_Tick
Public Shared Sub All_Users_Worker_Timer_Tick()
AllUsersWorker.RunWorkerAsync()
End Sub
Public Shared Sub AllUsersWorker_DoWork(ByVal sender As Object, ByVal e As DoWorkEventArgs)
tcpClient = New TcpClient
tcpClient.Connect("localhost", 9999)
networkStream = tcpClient.GetStream
If networkStream.CanWrite And networkStream.CanRead Then
Read_All_Connections()
End If
tcpClient.Close()
End Sub
Я хочу запустить поток BackgroundWorker, который устанавливает TCP-соединение, считывает / записывает некоторые данные, а затем закрывает соединение и повторяет каждые 2 секунды.
Я хочу физически открывать / закрывать соединение каждый раз, потому что время от времени сервер, к которому я подключаюсь, не отправляет данные, а вызов ReadByte останавливается в ожидании данных, и процесс не может продолжаться до тех пор, пока я не сброшу программу (следовательно, желая использовать другой поток для моего пользовательского интерфейса).
На данный момент я пытаюсь использовать DispatcherTimer с интервалом в 2 секунды для вызова Worker.RunWorkerAsync. Когда вызывается RunWorkerAsync, запускается метод DoEvents — в первый раз все работает нормально, но при последующем тике DispatcherTimer я обнаруживаю, что предыдущий поток не закрывается, поэтому при вызове RunWorkerAsync я получаю
«Этот фоновый рабочий в настоящее время занят и не может запускать несколько задач одновременно»
Каков наилучший способ, которым я могу этого добиться?
Есть ли лучший способ?
редактировать: думаю об этом. Было бы хорошо, если бы я мог каким-то образом встроить в нее сторожевой таймер, поэтому, если обнаруживается, что поток BackgroundWorker выполняется более 2 секунд, он завершается, поскольку это указывает на то, что поток был задержан tcp-соединением.
Ben
Комментарии:
1. Было бы полезно, если бы вы опубликовали некоторый код: как вы настраиваете DispatcherTimer и что находится в методе DoEvents.
2. Просто остановите таймер в обработчике событий Tick, запустите его обратно в обработчике событий RunWorkerCompleted. Или создайте новый BGW, если это имеет смысл (это редко бывает).
Ответ №1:
На самом BackgroundWorker.CancelAsync
деле не автоматически отменяет рабочий, но это всего лишь флаг, который входит в DoWork(object sender, DoWorkEventArgs e)
вызов как e.Cancel = true
и или BackgroundWorker.CancellationPending
так, что условие кода может проверить его и вернуться из DoWork()
, тем самым вручную отменяя саму работу.
Это то, что говорит MSDN…
Рабочий код должен периодически проверять свойство CancellationPending, чтобы убедиться, что для него установлено значение true.
Для автоматической отмены есть Thread.Abort()
вызов, но он может вызвать ThreadAbortException
. Так что будьте готовы попробовать поймать AllUsersWorker.RunWorkerAsync()
звонок.
Ответ №2:
Чтобы узнать, недоступен ли рабочий, вы можете проверить свойство: IsBusy
Поэтому, когда таймер тикает во второй раз, вы можете просто проверить, занят ли первый (в этом случае вы можете отменить его с помощью CancelAsync) и запустить новый.
Комментарии:
1. Только что попробовал это. IsBusy имеет значение True во второй раз, но даже вызов CancelAsync, похоже, не убивает его.
2. CancelAsync() просто устанавливает для свойства «CancellationPending» значение true в вашем backgroundworker, вы несете ответственность за проверку этого свойства и завершение событий, когда вы с ним сталкиваетесь. Я не занимаюсь VB, но я уверен, что вы можете найти множество примеров по всему Интернету.
3. Отмена и ожидание, пока он перестанет быть занятым, не работает. Это называется взаимоблокировкой.
4. Это не то, что я имел в виду. Я посоветовал, что если рабочий занят, отмените его и сделайте еще один, пока первый останавливается изящно. Нет взаимоблокировки, если он использует 2 объекта.