Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/jquery-ui/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 在分层体系结构中的主线程上调用委托_C#_Delegates_Multithreading_N Tier Architecture - Fatal编程技术网

C# 在分层体系结构中的主线程上调用委托

C# 在分层体系结构中的主线程上调用委托,c#,delegates,multithreading,n-tier-architecture,C#,Delegates,Multithreading,N Tier Architecture,我有一个后台程序,我想定期维护gps位置的状态。当线程方法位于另一个类中时,我不清楚如何在ui层的主线程上调用委托。下面是示例代码。我的表单在加载时启动线程: public partial class MainScreen : Form { . . // form stuff . private void MainScreen_Load(object sender, EventArgs e) { var gpsStatusManag

我有一个后台程序,我想定期维护gps位置的状态。当线程方法位于另一个类中时,我不清楚如何在ui层的主线程上调用委托。下面是示例代码。我的表单在加载时启动线程:

public partial class MainScreen : Form
    {
    .
    . // form stuff
    .
    private void MainScreen_Load(object sender, EventArgs e)
    {
        var gpsStatusManager = new GpsStatusManager();
        Thread t = new Thread(gpsStatusManager.UpdateLocation);
        t.IsBackground = true;
        t.Start();
    }

    delegate void GpsDataParameterDelegate(GpsStatus value);
    public void UpdateGpsStatus(GpsStatus value)
    {
        if (InvokeRequired)
        {
            // We're not in the UI thread, so we need to call BeginInvoke
            BeginInvoke(new GpsDataParameterDelegate(UpdateGpsStatus), new object[] { value });
            return;
        }
        // Must be on the UI thread if we've got this far
        gpsStatus.SetGpsStatus(value);
    }
}
我有一个用于gps信息的域对象类:

public class GpsStatus
{
    public void SetGpsStatus(GpsStatus gpsStatus)
    {
        Latitude = gpsStatus.Latitude;
        Longitude = gpsStatus.Longitude;
        CurrentDateTime = gpsStatus.CurrentDateTime;
        NumberOfSatellites = gpsStatus.NumberOfSatellites;
        TotalNumberSatellites = gpsStatus.TotalNumberSatellites;
    }

    public float Latitude { get; private set; }
    public float Longitude { get; private set; }
    public DateTime CurrentDateTime { get; private set; }
    public int NumberOfSatellites { get; private set; }
    public int TotalNumberSatellites { get; private set; }
}
然后,我的manager类,在该类中我更新辅助线程中的状态:

public class GpsStatusManager
{
    private GpsStatus _gpsStatus;

    public void UpdateLocationx()
    {
        while (UpdateGpsData()) 
        {
            Thread.Sleep(2000);
        }
    }

    private bool UpdateGpsData()
    {
        SError error;
        SGpsPosition gpsPosition;
        try
        {
            if (CApplicationAPI.GetActualGpsPosition(out error, out gpsPosition, true, 0) != 1)
                return false;
        }
        catch (Exception)
        {
             return false;
        }

        var numberOfSatellites = gpsPosition.Satellites;
        var totalSatellites = gpsPosition.satellitesInfo;
        var datetime = gpsPosition.Time;
        var lat = gpsPosition.Latitude;
        var lon = gpsPosition.Longitude;
        _gpsStatus.SetGpsStatus(lat, lon, datetime, numberOfSatellites, totalSatellites);

        //How do I invoke the delegate to send the _gpsStatus data to my main thread?
        return true;
    }
}
谢谢您的帮助。

您应该使用

在UI线程中(在任何类中),将一个字段(可能是
static
)设置为
SynchronizationContext.Current


然后,您可以在保存的实例上调用
Send
Post
,以在UI线程上执行代码。

这里有一种方法可以做到这一点,我不知道:

public class GpsStatusEventArgs : EventArgs
{
    public GpsStatus Status { get; private set; }
    public GpsStatusEventArgs(GpsStatus status)
    {
        Status = status;
    }
}

public class GpsStatusManager
{
    ...
    public event EventHandler<GpsStatusEventArgs> GpsStatusUpdated;

    private void OnGpsStatusUpdated(GpsStatus gpsStatus)
    {
        EventHandler<GpsStatusEventArgs> temp = GpsStatusUpdated;
        if (temp != null)
            temp.Invoke(this, new GpsStatusEventArgs(gpsStatus));
    }

}

public partial class MainScreen : Form
{
    ...
    private void MainScreen_Load(object sender, EventArgs e)
    {
        var gpsStatusManager = new GpsStatusManager();
        gpsStatusManager.GpsStatusUpdated += new EventHandler<GpsStatusEventArgs>(GpsStatusManager_GpsStatusUpdated);
        ...
    }

    private void GpsStatusManager_GpsStatusUpdated(object sender, GpsStatusEventArgs e)
    {
        UpdateGpsStatus(e.Status);
    }
    ...
}

下面是使用
ISynchronizeInvoke
接口的另一种方法。这与
System.Timers.Timer
类用于引发
已用事件的模式相同

public class GpsStatusManager
{
  public ISynchronizeInvoke SynchronizingObject { get; set; }

  public event EventHandler Update;

  public void UpdateGpsData()
  {
    // Code omitted for brevity.
    OnUpdate(_gpsStatus);
    return true;
  }

  private OnUpdate(GpsStatus status)
  {
    if (SynchronizingObject != null && SynchronizingObject.IsInvokeRequired)
    {
      ThreadStart ts = () => { OnUpdate(status); };
      SynchronizingObject.Invoke(ts, null);
    }
    else
    {
      if (Update != null)
      {
        Update(this, status);
      }
    }
  }

  public class UpdateEventArgs : EventArgs
  {
    public GpsStatus Status { get; set; }
  }
}
public class GpsStatusManager
{
  public ISynchronizeInvoke SynchronizingObject { get; set; }

  public event EventHandler Update;

  public void UpdateGpsData()
  {
    // Code omitted for brevity.
    OnUpdate(_gpsStatus);
    return true;
  }

  private OnUpdate(GpsStatus status)
  {
    if (SynchronizingObject != null && SynchronizingObject.IsInvokeRequired)
    {
      ThreadStart ts = () => { OnUpdate(status); };
      SynchronizingObject.Invoke(ts, null);
    }
    else
    {
      if (Update != null)
      {
        Update(this, status);
      }
    }
  }

  public class UpdateEventArgs : EventArgs
  {
    public GpsStatus Status { get; set; }
  }
}