代码之家  ›  专栏  ›  技术社区  ›  Ilya Volodin

从工作线程c_cf在主线程中引发事件

  •  2
  • Ilya Volodin  · 技术社区  · 15 年前

    我可能有一个简单的问题。我正在使用interop调用CompactFramework中的异步函数。在我得到执行结果之后,我想引发一个事件,它将被窗体捕获,并且基于结果,我将在屏幕上呈现一些数据。但是,问题是,当interop函数返回结果时,它在工作线程上返回结果,如果引发事件,它将停留在工作线程上,并且除非使用invoke,否则无法呈现表单中的任何数据。

    有人能提出一种将工作线程合并到主线程上的方法吗?从主线程引发事件?我发现了几个例子,它们循环遍历订阅事件的委托,并使用BeginInvoke在主线程中引发事件,但是,它们都使用isynchronizeInvoke,这在Compact框架中不可用。

    我的代码如下:

    public delegate void CellTowerFoundEventHandler(CellTower towerInfo);
    
    public class CellTowerProvider
    {
        public delegate void RILRESULTCALLBACK(uint dwCode, IntPtr hrCmdID, IntPtr lpData, uint cbData, uint dwParam);
        public delegate void RILNOTIFYCALLBACK(uint dwCode, IntPtr lpData, uint cbData, uint dwParam);
        private RILCELLTOWERINFO towerDetails;
        private CellTower cellTowerInfo;
        private IntPtr radioInterfaceLayerHandle;
    
        public CellTowerProvider()
        {
            radioInterfaceLayerHandle = IntPtr.Zero;
            IntPtr radioResponseHandle = IntPtr.Zero;
    
            // Initialize the radio layer with a result callback parameter.
            radioResponseHandle = RIL_Initialize(1, new RILRESULTCALLBACK(CellDataCallback), null, 0, 0, out radioInterfaceLayerHandle);
    
            // The initialize API call will always return 0 if initialization is successful.
            if (radioResponseHandle != IntPtr.Zero)
            {
                return;
            }
    
            // Query for the current tower data.
            radioResponseHandle = RIL_GetCellTowerInfo(radioInterfaceLayerHandle);
        }
    
        public void CellDataCallback(uint dwCode, IntPtr hrCmdID, IntPtr lpData, uint cbData, uint dwParam)
        {
            // Refresh the current tower details
            towerDetails = new RILCELLTOWERINFO();
    
            // Copy result returned from RIL into structure
            Marshal.PtrToStructure(lpData, towerDetails);
    
            cellTowerInfo = new CellTower()
            {
                TowerId = Convert.ToInt32(towerDetails.dwCellID),
                LocationAreaCode = Convert.ToInt32(towerDetails.dwLocationAreaCode),
                MobileCountryCode = Convert.ToInt32(towerDetails.dwMobileCountryCode),
                MobileNetworkCode = Convert.ToInt32(towerDetails.dwMobileNetworkCode),
            };
    
            if (CellTowerFound != null)
                CellTowerFound(cellTowerInfo);
    
            // Release the RIL handle
            RIL_Deinitialize(radioInterfaceLayerHandle);
        }
    
    }
    
    3 回复  |  直到 15 年前
        1
  •  2
  •   ctacke    15 年前

    为什么不在库对象的ctor中创建控件?如果假定库实例是在UI线程中创建的,则可以调用Control.Invoke on 那个 控件位于库内部,事件调用将位于使用者的UI线程上。

    当然,这并不是万无一失的。使用者可能会在工作线程中创建实例,但它至少提供了您所追求的目标的某种级别,如果他们使用工作线程,他们实际上会期望事件无论如何都需要调用。

        2
  •  2
  •   Henk Holterman    15 年前

    好吧,invoke是将线程与主线程“合并”(同步)的(正确的)方法。最简单的方法是使用控件(如mainform)和调用 ctl.Invoke(myDelegate) .

    第二,我们 提升 事件和 例外情况。使用正确的词语可以避免混淆。

        3
  •  2
  •   Reed Copsey    15 年前

    这取决于您使用什么工具箱来显示“主线程”中的数据。如果您使用的是Windows窗体,那么应该能够使用control.invoke或control.begininvoke将事件封送回UI线程。这在紧凑框架中得到了支持。

    大多数示例使用isynchronizeinvoke而不是控件-但代码应该相同。但是,您需要在代码中引用一个UI元素,以便在引发事件时与对BeginInvoke的调用一起使用。