【问题标题】:Is Threading Communication Needed Here?这里需要线程通信吗?
【发布时间】:2015-12-28 09:51:20
【问题描述】:

我正在尝试让此代码在到达一天中的特定时间后向屏幕添加一些内容。它被操纵到一个事件。该代码适用于单线程程序,但不适用于线程,这是我需要的。数据会根据需要添加,但不会像在单线程执行时那样显示在屏幕上(timeStackStackPanelTimeEntryUserControl)。

代码:

Mainwindow.xaml.cs

public partial class MainWindow : Window
{
    public MainWindow()
    {
        SM = new SessionManager();
        SM.NewDayEvent += SplitSession;
        InitializeComponent();
        //Code removed for clarity
    }

    private void SplitSession(object sender, EventArgs ea)
    {
        SM.SplitSession();
        string s =((TimeEntry)SM.Entries.Last(x=>x.GetType()==typeof(TimeEntry))).Data.Comment;
        AddSessionStamp();
        entryAdder_Click(null, null);
        ((TimeEntry)SM.Entries.Last(x => x.GetType() == typeof(TimeEntry))).Data.Comment = s;
        this.Focus();
    }
    private void AddSessionStamp()
    {
        TextBlock timeStamp = new TextBlock();
        timeStamp.Text = "-----------" + SM.CurrentSession.Name + "-----------";
        timeStack.Children.Add(timeStamp);
    }
    private void entryAdder_Click(object sender, RoutedEventArgs e)
    {
        //Subscribe to the assorted events
        TimeEntry newTE = SM.addNewTimeEntry();
        //Subscribe to the assorted events
        RegisterToTimeEntry(newTE);
        timeStack.Children.Add(newTE);
    }
}

SessionManager.cs

public class SessionManager : INotifyPropertyChanged
{
    public delegate void NewDayEventHandler(object sender, EventArgs ea);
    public event NewDayEventHandler NewDayEvent;

    private Timer _timer;
    private Stopwatch _clockWatch;
    private DateTime current_time;
    #region Properties
    public DateTime CurrentTime
    {
        get
        {
            return DateTime.Now;
        }
        set
        {
            if (current_time != value)
            {
                current_time = value;
                OnPropertyChanged("CurrentTime");
            }
        }
    }

    public List<Session> OpenSessions { get; private set; }

    public ObservableCollection<UIElement> Entries { get; private set; }

    public Session CurrentSession
    {
        get
        {
            return current_session;
        }
        set
        {
            if (current_session != value)
            {
                current_session = value;
                OnPropertyChanged("CurrentSession");
            }
        }
    }

    #endregion


    public SessionManager()
    {
        _clockWatch = new Stopwatch();
        _timer = new Timer(1000);//one second
        _timer.Elapsed += timerElapsed;

        //Code removed for clarity
        current_time = new DateTime();
        CurrentTime = DateTime.Now;
        _timer.Start();
    }


    #region Methods
    #region Event Methods
    /// <summary>
    /// Registered to Timer.Elapsed Event
    /// (See constructor)
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    public void timerElapsed(object sender, ElapsedEventArgs e)
    {
        CurrentTime = DateTime.Now;
        if ((CurrentTime.TimeOfDay.Hours == 13 &&
            CurrentTime.TimeOfDay.Minutes == 23 &&
            CurrentTime.TimeOfDay.Seconds == 0) &&
            NewDayEvent != null)
        {
            NewDayEvent(this, new EventArgs());
        }
    }

    #endregion

    #region Class Methods

    private void OnPropertyChanged([CallerMemberName] string member_name = "")
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(member_name));
        }
    }
    #endregion
    #endregion
    public void SplitSession()
    {
        Session prevSesh = CurrentSession;
        OpenSessions.Add(new Session());
        CurrentSession = OpenSessions.Last();
        current_session.addComment(
            ((TimeEntry)Entries.Last(
            x => x.GetType() == typeof(TimeEntry))
            ).Data.Comment);
    }
}

【问题讨论】:

    标签: c# wpf multithreading xaml events


    【解决方案1】:

    事件处理函数在与引发事件的线程相同的线程中执行。问题是您无法从 Dispatcher 线程的另一个线程更新 UI。您需要在 Dispatcher Invoke 或 BeginInvoke 中执行回调函数(或至少是更新部分):

    Application.Current.Dispatcher.Invoke(new Action(() => {
        //your UI update
    }));
    

    【讨论】:

    • 您能详细说明一下吗?评论在哪里,是我放 NewDayEvent() 的地方吗?还是 SplitSession 方法代码?
    • 两者都可以,但是在 Dispatcher 线程中执行事件引发是不合逻辑的,因为它是消费者特定的行为。所以你应该在 Invoke 中包装 SplitSession 内容
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-06-22
    • 2017-04-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多