从辅助线程C#CF主线程抛出事件 [英] Throw event in the main thread from worker thread C# CF

查看:171
本文介绍了从辅助线程C#CF主线程抛出事件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有,恐怕是一个简单的问题。我使用互操作来调用CompactFramework异步函数。之后我得到的执行结果,我想提出一个事件,将由形式被捕获,并在基于结果的,我会在屏幕上渲染一些数据。但问题是,当互操作函数返回一个结果,它返回它在一个工作线程,如果我提出一个事件,它会留在工作线程上,我不能在形式呈现的任何数据,除非我使用调用。



有人可以提出一个方法来辅助线程驶入主线程?并提高从主线程的事件?我找到了几个例子来遍历代表订阅了该事件,并使用的BeginInvoke提高在主线程的事件,但是,它们都使用ISynchronizeInvoke,这是不是在Compact Framework中可用。



我的代码如下:

 公共委托无效CellTowerFoundEventHandler(CellTower的towerInfo); 

公共类CellTowerProvider
{
公众委托无效RILRESULTCALLBACK(UINT dwCode,IntPtr的hrCmdID,IntPtr的的lpData,UINT cbData,UINT dwParam);
公众委托无效RILNOTIFYCALLBACK(UINT dwCode,IntPtr的的lpData,UINT cbData,UINT dwParam);
私人RILCELLTOWERINFO towerDetails;
私人CellTower的cellTowerInfo;
私人的IntPtr radioInterfaceLayerHandle;

公共CellTowerProvider()
{
radioInterfaceLayerHandle = IntPtr.Zero;
IntPtr的radioResponseHandle = IntPtr.Zero;

//初始化一个结果回调参数无线层。
radioResponseHandle = RIL_Initialize(1,新RILRESULTCALLBACK(CellDataCallback),NULL,0,0,出radioInterfaceLayerHandle);

//初始化API调用总是返回0,如果初始化成功。
如果(radioResponseHandle = IntPtr.Zero!)
{
的回报;
}

//查询当前塔的数据。
radioResponseHandle = RIL_GetCellTowerInfo(radioInterfaceLayerHandle);
}

公共无效CellDataCallback(UINT dwCode,IntPtr的hrCmdID,IntPtr的的lpData,UINT cbData,UINT dwParam)
{
//刷新当前塔的细节
towerDetails =新RILCELLTOWERINFO();

//复制结果从RIL返回到结构
Marshal.PtrToStructure(参数lpData,towerDetails);

cellTowerInfo =新CellTower的()
{
TowerId = Convert.ToInt32(towerDetails.dwCellID),
LocationAreaCode = Convert.ToInt32(towerDetails.dwLocationAreaCode),
MobileCountryCode = Convert.ToInt32(towerDetails.dwMobileCountryCode),
MobileNetworkCode = Convert.ToInt32(towerDetails.dwMobileNetworkCode),
};

如果(CellTowerFound!= NULL)
CellTowerFound(cellTowerInfo);

//松开手柄RIL
RIL_Deinitialize(radioInterfaceLayerHandle);
}

}


解决方案

为什么不创建库中的对象的构造函数控件?如果假设库实例在UI线程创建的,你可以调用Control.Invoke上的的内部控制,以您的图书馆,以及事件的呼叫会在消费者在UI线程上。



当然,这是不可能不犯错。消费者可能会在工人创建实例,但它至少提供了你以后,如果他们使用一个工作线程,他们会想到居然事件需要调用调用反正一定程度。


I have, what probably is, a simple problem. I'm using interop to call an asynchronous function in CompactFramework. After I get result of the execution, I would like to raise an event, that will be caught by the form, and based on the results, I would render some data on the screen. The problem, however, is that when interop function returns a result, it returns it on a worker thread, and if I raise an event, it will stay on the worker thread and I can't render any data in the form, unless I use Invoke.

Can somebody suggest a way to merge worker thread onto the main thread? And raise an event from the main thread? I found a few examples that loop through the delegates subscribed to the event and use BeginInvoke to raise an event in main thread, however, they all use ISynchronizeInvoke, which is not available in Compact Framework.

My code is below:

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

}

解决方案

Why not create a Control in the ctor of your library object? If you assume that the library instance is created in the UI thread, you can then call Control.Invoke on that control internal to your library, and the event call will be on the UI thread in the consumer.

Of course this isn't infallible. The consumer might create the instance in a worker, but it at least provides some level of what you're after and if they use a worker thread, they'd actually expect events to need an Invoke call anyway.

这篇关于从辅助线程C#CF主线程抛出事件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆