Метод с тайм-аутом. Проблема взаимодействия с глобальными функциями и объектами.
В проекте используется внешняя библиотека, работа с её объектами производится в ф-ии DataRequest.
Если вызывать DataRequest в оснвном потоке (вставить её в цикл For Each метода UpdateData, то всё работает). Но ф-ия может долго выполняться и мне необходимо реализовать для неё принудительное завершение по тайм-ауту. Написал код. который приведен, ниже. Перестала вызываться ф-ия MyExternalDLL.ReadData(p_KEY), полагаю из-за того что она стала выполняться в отдельном потоке. Насколько, я знаю работать с объектами из основного потока, в дочерних нельзя. :rolleyes: Нужно сделать Invoke. Попытался через Reflection вызвать DataRequest, но всё равно не работает.
Подскажите поджалуйста как правильно сделать. :confused:
Imports System.Reflection
Module modMain
Private WithEvents Core as clsCore=new clsCore
<STAThread()> Sub Main()
Do While Not Console.KeyAvailable
Core.UpdateData() 'Обновление данных
Application.DoEvents()
Loop
End Sub
End Module
Public Class clsCORE
Private Key As String = ""
Public Sub UpdateData()
For Each Key In CNC.Keys
Method()
Next
End Sub
Private Sub Method()
Const TimeOut As Int32 = 1000
Dim [handles] As WaitHandle() = New WaitHandle() {New AutoResetEvent(False)}
ThreadPool.QueueUserWorkItem(New WaitCallback(AddressOf Worker), [handles](0))
Dim finished As Boolean = WaitHandle.WaitAll([handles], TimeOut, True)
If finished Then
Console.WriteLine("Worker function finished sucessfully")
Else
Console.WriteLine([String].Format("Worker function time out({0})!", TimeOut))
End If
End Sub
Private Sub Worker(ByVal state As Object)
Dim are As AutoResetEvent = DirectCast(state, AutoResetEvent)
Dim MyType As Type = GetType(clsCORE)
Dim MyMethodInfo As MethodInfo = MyType.GetMethod("DataRequest")
Dim MyInstance As Object = Activator.CreateInstance(MyType)
Dim args() As Object = New Object() {Me.Key}
Dim Value As Object = MyMethodInfo.Invoke(Core, args)
Console.WriteLine(Value.ToString)
are.[Set]()
End sub
Public Function DataRequest(ByVal p_KEY As String) As Object
Return MyExternalDLL.ReadData(p_KEY)
End Function
End Class
Подскажите поджалуйста как правильно сделать. :confused:
Попробовал не получилось, в Task action функция MyExternalDLL.ReadData(p_KEY) тоже возвращает 0. Т.к. Task выполняется повидимому тоже в отдельном потоке.
Подскажите пожалуйста какие классы фреймворка использовать чтобы решить мою задачу.
Пока я вижу только одно решение не использовать внешние объекты, объявить их внутри процедуры Worker и отдавать данные наверх (этот вариант не подходит, т.к. необходимо каждый раз коннектиться к оборудованию внутри Worker).
Я также пробовал решить эту задачу через System.Threading.Tasks (TPL + Cancellation) и в этом случае Return MyExternalDLL.ReadData(p_KEY) тоже возвращает 0.
Мне необходимо написать сервер, который рассылает киентам параметры полученные с оборудования по сети:
1.Клиент-сервер я написал
2.В сервере необходимо подключиться к удалённому оборудованию (это занимает время).
3.В сервере в цикле обновляю параметры оборудования, связь ненадёжная поэтому, чтобы сервер не подвисал нужно ввести отмену считывания параметра по тайм-ауту.
4.По завершению цикла клиентам разрешается получение данных.
Как реализовать 3. другим способом ? :confused:
Где выполняется ожидание? В управляемом коде или нативном? Если в последнем, то прервать ожидание можно только если есть соответствующее нативное АПИ.
Считывается температура двигателя, она не может быть ноль постоянно. Для проверки объявил MyExternalDLL в потоке где вызывается MyExternalDLL.ReadData(p_KEY). Сразу заработало, ф-ия возвращает значение температуры (39-42).
С похожей проблемой встречался при работе с классом BackgroundWorker, там аналогично в событии DoWork ф-ии глобально объявленных объектов из библиотек не выполняются.
С похожей проблемой встречался при работе с классом BackgroundWorker, там аналогично в событии DoWork ф-ии глобально объявленных объектов из библиотек не выполняются.
По-видимому нужно в потоках отличных от основного выполнять инициализацию статических переменных потока (thread static).
В управляемом.
Решил делать следующим образом:
Dim are As AutoResetEvent = DirectCast(state, AutoResetEvent)
Static MyExternalDLL as ExternalDLL = New ExternalDLL(Device_Address)
...
''''''Dim Temperature As Single= MyExternalDLL.ReadData(p_KEY) так работает через раз, периодически возвращает 0.
Static Temperature As Single= MyExternalDLL.ReadData(p_KEY) 'так всё ок!
Console.WriteLine("Temperature: " & Temperature.ToString)
are.[Set]()
End sub
Я думаю
Я думаю
Я не понимаю необходимости использования статических переменных.
Почему бы не создать отдельный класс для работы с этой библиотекой?