2010-09-23 5 views
0

Я неоднократно вызываю метод с BeginInvoke. После каждого вызова я вызываю EndInvoke.Заявки на участие второго BeginInvoke уже завершены. Зачем?

Проблема в том, что для второго вызова член IsCompleted в возвращенном IAsyncResult установлен в true IMMEDIATELY после вызова BeginInvoke.

Это приводит к неисправности, так как программа тогда думает, что второй вызов сделан.

Почему это делается, и как я могу определить, когда второй звонок ДЕЙСТВИТЕЛЬНО завершен?

Declarations: 
IAsyncResult ar; 
Mercury.J4000.Ui.frmMain.doPrintsDelegate printCallback; 


The BeginInvoke call: 
ar = printCallback.BeginInvoke (jobNameArray, copies, distances, null, null); 


The EndInvoke call (in another method): 
printCallback.EndInvoke(ar); 
+0

Не могли бы Вы поделитесь своим кодом? –

+0

Пожалуйста, покажите код. Не заставляйте нас угадывать, что вы сделали неправильно. –

+0

Обновите свой вопрос кодом, а не размещайте его как комментарий. –

ответ

2

Я предполагаю, что вы используете одну и ту же переменную ar в обоих вызовах, потому что вы объявили ее как поле. Каждый вызов должен иметь свой собственный экземпляр; объявите поле как List<IAsyncResult> и напишите требуемую сантехнику для ее инициализации и сопоставьте каждый результат с каждым вызовом. Вы не дали достаточно коды для нас, чтобы помочь вам с той частью

+0

Да, я использую одну и ту же переменную, потому что в документации Microsoft говорится об этом параметре EndInvoke: «IAsyncResult, который представляет конкретную асинхронную операцию вызова, возвращаемую при вызове BeginInvoke». – alankdkd

+0

@alankdkd представляет собой конкретную асинхронную операцию вызова. Это означает, что вам нужна новая переменная для отслеживания результата каждый раз, когда вы вызываете BeginInvoke. –

+0

@alankdkd - тогда, пожалуйста, отметьте мой ответ как ответ (так как джим ответил через 10 минут после меня с тем же ответом) – x0n

2

Я предполагаю, что вы делаете что-то вроде этого (на самом деле этот ответ является предположением, потому что вы не дали достаточно коды.):

IAsyncResult ar; 
ar = printCallback.BeginInvoke(...); 
// do some other stuff 
ar = printCallback.BeginInvoke(...); 

Если первая операция асинхронного сканирования не завершена до начала второго запуска, то вы потеряете значение IAsyncResult. Он перезаписывается вторым вызовом.

Как-то вам нужно отслеживать отдельные ссылки IAsyncResult и связывать их с вашими звонками. Если у вас только один или два, вы можете легко отслеживать отдельные переменные или коллекцию (List или массив, как правило).

Этот вопрос может помочь вам: Can I use a single instance of a delegate to start multiple Asynchronous Requests?

Я также полагаю, что вы рассмотрите возможность использования обратных вызовов для асинхронных делегатов. Таким образом, правильный IAsyncResult передается как параметр обратного вызова, и нет никакой возможности для двусмысленности. Однако, используя AsyncCallback, может потребоваться серьезный рефакторинг вашего кода.