Throw event in the main thread from worker thread C# CF

喜你入骨 提交于 2019-12-11 03:46:28

问题


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

}

回答1:


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.




回答2:


Well, Invoke is the (proper) way to 'merge' (sync) a Thread with with the main thread. The easiest ways is to use a Control (eg MainForm) and call ctl.Invoke(myDelegate).

And second, we raise events and throw exceptions. Using the right words avoids confusion.




回答3:


This depends on what toolkit you're using to display data in your "main thread". If you're using Windows Forms, you should be able to use Control.Invoke or Control.BeginInvoke to marshal the event back onto the UI thread. This is supported in the Compact Framework.

Most samples use ISynchronizeInvoke instead of a control - but the code should be identical. You'll need a reference to a UI element in your code, though, to use with the call to BeginInvoke when you raise your event.



来源:https://stackoverflow.com/questions/1983066/throw-event-in-the-main-thread-from-worker-thread-c-sharp-cf

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!