Спрашивающий
Метод с тайм-аутом. Проблема взаимодействия с глобальными функциями и объектами.

Вопрос
-
Есть экземпляр класса Core. В процедуре Main консольного приложения, вызываем Core.UpdateData.
В проекте используется внешняя библиотека, работа с её объектами производится в ф-ии DataRequest.
Если вызывать DataRequest в оснвном потоке (вставить её в цикл For Each метода UpdateData, то всё работает). Но ф-ия может долго выполняться и мне необходимо реализовать для неё принудительное завершение по тайм-ауту. Написал код. который приведен, ниже. Перестала вызываться ф-ия MyExternalDLL.ReadData(p_KEY), полагаю из-за того что она стала выполняться в отдельном потоке. Насколько, я знаю работать с объектами из основного потока, в дочерних нельзя. :rolleyes: Нужно сделать Invoke. Попытался через Reflection вызвать DataRequest, но всё равно не работает.
Подскажите поджалуйста как правильно сделать. :confused:Imports System.Threading 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
28 января 2011 г. 9:21
Все ответы
-
Если вы хотите с помощью Invoke вызвать метод DataRequest в основном потоке, то это ни к чему не приведет. Метод Invoke не вызовет метод DataRequest в основном потоке, он просто вызовет DataRequest в том же потоке. Это равносильно просто вызову DataRequest. А если делать графическое приложение и использовать метод Control.Invoke, то да, это приведет к вызову метода в основном потоке, но тогда метод DataRequest вызовется и будет работать до тех пор, пока не отработает, событие таймаута не прервет его. И все идея таймаута потеряет смысл.
Для связи [mail]28 января 2011 г. 15:25 -
Если вы хотите с помощью Invoke вызвать метод DataRequest в основном потоке, то это ни к чему не приведет. Метод Invoke не вызовет метод DataRequest в основном потоке, он просто вызовет DataRequest в том же потоке. Это равносильно просто вызову DataRequest. А если делать графическое приложение и использовать метод Control.Invoke, то да, это приведет к вызову метода в основном потоке, но тогда метод DataRequest вызовется и будет работать до тех пор, пока не отработает, событие таймаута не прервет его. И все идея таймаута потеряет смысл.
Для связи [mail]
Подскажите пожалуйста какие классы фреймворка использовать чтобы решить мою задачу.Пока я вижу только одно решение не использовать внешние объекты, объявить их внутри процедуры Worker и отдавать данные наверх (этот вариант не подходит, т.к. необходимо каждый раз коннектиться к оборудованию внутри Worker).
Я также пробовал решить эту задачу через System.Threading.Tasks (TPL + Cancellation) и в этом случае Return MyExternalDLL.ReadData(p_KEY) тоже возвращает 0.
Мне необходимо написать сервер, который рассылает киентам параметры полученные с оборудования по сети:
- Клиент-сервер я написал
- В сервере необходимо подключиться к удалённому оборудованию (это занимает время).
- В сервере в цикле обновляю параметры оборудования, связь ненадёжная поэтому, чтобы сервер не подвисал нужно ввести отмену считывания параметра по тайм-ауту.
- По завершению цикла клиентам разрешается получение данных.
Как реализовать 3. другим способом ?
28 января 2011 г. 18:35 -
Если в методе есть цикл, то завершить его можно при прохождении очередной итерации цикла, примерно так.
class MainClass { static void Main() { Runner r = new Runner(10000); Action act = new Action(r.Run); act.BeginInvoke(null, null); Console.ReadLine(); } } public class Runner { DateTime _start; Int32 _timeOut; private Runner() { } public Runner(Int32 timeOut) { if (timeOut <= 0) throw new ArgumentOutOfRangeException("timeOut"); _timeOut = timeOut; } public void Run() { _start = DateTime.Now; while (true) { if ((DateTime.Now - _start).TotalMilliseconds > _timeOut) break; //работа System.Threading.Thread.Sleep(100); } } }
7 апреля 2011 г. 14:10