繁体   English   中英

从工作线程C#CF在主线程中引发事件

[英]Throw event in the main thread from worker thread C# CF

我有一个简单的问题。 我正在使用互操作在CompactFramework中调用异步函数。 得到执行结果后,我想引发一个事件,该事件将被表单捕获,并根据结果在屏幕上呈现一些数据。 但是问题是,当互操作函数返回结果时,它会在工作线程上返回结果,如果我引发一个事件,它将保留在工作线程上,并且我无法以该形式呈现任何数据,除非我使用Invoke。

有人可以建议一种将工作线程合并到主线程的方法吗? 并从主线程引发一个事件? 我发现了一些示例,这些示例遍历订阅事件的委托,并使用BeginInvoke在主线程中引发事件,但是,它们都使用ISynchronizeInvoke,在Compact Framework中不可用。

我的代码如下:

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);
    }

}

好吧,调用是与主线程“合并”(同步)线程的(正确)方法。 最简单的方法是使用Control(例如MainForm)并调用ctl.Invoke(myDelegate)

其次,我们引发事件并引发异常。 使用正确的词可以避免混淆。

这取决于您使用哪种工具箱在“主线程”中显示数据。 如果您使用的是Windows窗体,则应该可以使用Control.Invoke或Control.BeginInvoke将事件封送回UI线程。 精简框架支持此功能。

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

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

当然这不是万无一失的。 使用者可以在工作程序中创建实例,但是它至少提供了您所需要的信息,如果他们使用工作程序线程,他们实际上希望事件仍然需要调用Invoke。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM