2013-05-05 4 views
0

У меня есть форма Form1 с кнопкой и текстовым полем. Когда я нажимаю на кнопку, я должен получить некоторые данные с USB-устройства. По какой-то причине он работает правильно только около 2% (я смог получить 2 правильных ответа из 100 кликов). Вот код для Form1:Asynccallback в dll вызывает форму для замораживания

namespace Test_onForm1 
{ 
    public partial class Form1 : Form 
    { 
     public Form1() 
     { 
      InitializeComponent(); 
     } 

     private void button1_Click(object sender, EventArgs e) 
     { 
      Lib1.FindHID.TransferInputAndOutputReports(0xC0); //request specific data from USB device 
     } 
    } 
} 

Регулируя USB связи код в DLL Lib1 (фрагменты кода ниже):

namespace Lib1 
{  
    public static class FindHID 
    { 
    private static void TransferInputAndOutputReports(UInt16 repType) 
    { 
     //some code here sending request to USB device... and then read what came from USB 
     ReadInput(); 
     //some code here     
    }  

    // Read an Input report. 
     private static void ReadInput() 
     { 
      Byte[] inputReportBuffer = null; 
      inputReportBuffer = new Byte[MyHid.Capabilities.InputReportByteLength]; 
     IAsyncResult ar = null; 

      if (fileStreamDeviceData.CanRead) 
     { 
     // RUNS UP TO THIS POINT and then Form1 freezes most of the time 
       fileStreamDeviceData.BeginRead(inputReportBuffer, 0, inputReportBuffer.Length, new AsyncCallback(GetInputReportData), inputReportBuffer);     
      } 
     } 

    private static void GetInputReportData(IAsyncResult ar) 
     { 
     // RARELY GETS HERE 
       Byte[] inputReportBuffer = null; 
       inputReportBuffer = (byte[])ar.AsyncState;    

    fileStremDeviceData.EndRead(ar); //waits for read to complete 
     // then code to update Form1 
    }  
    } 
} 
} 

Когда он не работает он останавливается около fileStreamDeviceData .BeginRead, а затем Form1 замерзает.

Для тестирования я создал совершенно новый проект и вместо того, чтобы использовать DLL, я скопировал весь DLL-код в Form1. Эта опция работает отлично в 100% случаев. Итак, мой вопрос, почему он не работает с DLL?

Обновление: когда мне повезет, и он начнет работать, он работает неопределенно, пока я не закрою приложение. Затем я должен продолжать пытаться заставить его работать снова. Как устранить эту проблему?

+0

Возможно, вы читаете больше байтов из-за 'inputReportBuffer.Length', чем есть доступные байты. Какой тип 'fileStreamDeviceData' и имеет ли он свойство' Доступно'? – Silvermind

+0

Число байтов правильное. Эта программа является копией моей оригинальной программы, которая отлично работает. Я ничего здесь не менял. Единственное, что я сделал, это переместить часть кода во вновь создаваемую DLL. Идея заключается в том, что я буду распространять DLL для своих друзей, чтобы они могли создавать собственное приложение, основанное на их потребностях. – mike5ocns

+0

ФайлStreamDeviceData является частным статическим FileStream и не имеет. Доступное свойство – mike5ocns

ответ

0

Скорее всего, проблема в том, что код в EndRead пытается обновить форму, но это не относится к потоку пользовательского интерфейса. Вам нужно синхронизировать с потоком пользовательского интерфейса, либо делая Form.Invoke, либо каким-то образом уведомляя форму, что данные готовы, чтобы поток пользовательского интерфейса мог выполнить обновление.

+0

У меня есть обновление пользовательского интерфейса через делегата (для простоты не показано в приведенном выше коде). Я отключил код до основного минимума для отладки. – mike5ocns

+0

Место, где вы видите комментарий: // RARELY GETS ЗДЕСЬ прямо сейчас У меня есть Console.Writeline («У меня есть это?»); и я не вижу этого в консоли. Он появится, когда мне повезет, а потом все будет работать. – mike5ocns

0

РЕШЕННЫЙ!

На сайте Microsoft: «Реализация BeginRead по потоку по умолчанию вызывает синхронный метод Read, что означает, что Read может блокироваться для некоторых потоков».

Я использовал .NET Framework 4.0 в Visual Studio 2010. Решено обновить до .NET Framework 4.5, который вместо этого имеет метод Stream.ReadAsync. Тем не менее, я не смог реализовать Stream.ReadAsync на Visual Studio 2010 (не знаю, почему, возможно, нуждается в обновлении до 2012 года?). Итак, с обновленной Framework 4.5 я попробовал свой код, и он работает ВСЕ ВРЕМЯ КАЖДЫЙ РАЗ.

+0

Спасибо, ребята, за помощь! – mike5ocns