dll中的Asynccallback导致Form冻结

时间:2013-05-05 14:23:00

标签: c# dll asynccallback iasyncresult

我有一个表单Form1,带有一个按钮和文本框。 当我点击按钮时,我应该从USB设备获取一些数据。 出于某种原因,它只能正常工作2%(我在100次点击中得到了2个正确答案)。 这是Form1的代码:

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?

更新:当我幸运并开始工作时,它会无限期地工作,直到我关闭申请。然后,我必须继续努力让它再次运作。 如何解决这个问题?

2 个答案:

答案 0 :(得分:0)

问题很可能是EndRead中的代码正在尝试更新表单,但它不在UI线程上。您必须通过执行Form.Invoke或以某种方式通知表单数据已准备好以便UI线程可以执行更新来与UI线程同步。

答案 1 :(得分:0)

解决!

在Microsoft网站上找到: “流上的BeginRead的默认实现同步调用Read方法,这意味着Read可能会阻塞某些流。”

我在Visual Studio 2010上使用.NET Framework 4.0。 决定更新到具有Stream.ReadAsync方法的.NET Framework 4.5。但是,我无法在Visual Studio 2010上实现Stream.ReadAsync(不知道原因,可能需要更新到2012年?)。 因此,使用更新的Framework 4.5,我尝试了我的代码,它可以随时工作。