C# 这里需要线程通信吗?
我正试图让这段代码在一天中的某个特定时间到达后向屏幕添加一些内容。这是为一个事件而设的。这段代码可以在单线程程序上运行,但不能使用线程,这正是我所需要的。数据会根据需要添加,但不会像在单线程执行时那样显示在屏幕上(C# 这里需要线程通信吗?,c#,wpf,multithreading,xaml,events,C#,Wpf,Multithreading,Xaml,Events,我正试图让这段代码在一天中的某个特定时间到达后向屏幕添加一些内容。这是为一个事件而设的。这段代码可以在单线程程序上运行,但不能使用线程,这正是我所需要的。数据会根据需要添加,但不会像在单线程执行时那样显示在屏幕上(timeStack是一个StackPanel,TimeEntry是一个UserControl) 代码: main window.xaml.cs: public partial class MainWindow : Window { public MainWindow()
timeStack
是一个StackPanel
,TimeEntry
是一个UserControl
)
代码:
main window.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);
}
}
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);
}
}
SessionManager.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);
}
}
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);
}
}
公共类会话管理器:INotifyPropertyChanged
{
公共委托void NewDayEventHandler(对象发送方,EventArgs ea);
公共事件NewDayEventHandler NewDayEvent;
私人定时器;
私人秒表(钟表),;
私有日期时间当前时间;
#区域属性
公共日期时间当前时间
{
得到
{
返回日期时间。现在;
}
设置
{
如果(当前_时间!=值)
{
当前时间=数值;
OnPropertyChanged(“当前时间”);
}
}
}
公共列表OpenSessions{get;private set;}
公共可观测集合项{get;private set;}
公开会议当前会议
{
得到
{
返回当前会话;
}
设置
{
if(当前会话!=值)
{
当前会话=值;
OnPropertyChanged(“当前会话”);
}
}
}
#端区
公共会话管理器()
{
_钟表=新秒表();
_定时器=新定时器(1000);//一秒钟
_timer.appeased+=timerecursed;
//为清晰起见,代码已删除
当前时间=新日期时间();
CurrentTime=DateTime.Now;
_timer.Start();
}
#区域方法
#区域事件方法
///
///已注册到计时器。已用事件
///(见施工图)
///
///
///
public void timerecursed(对象发送方,ElapsedEventArgs e)
{
CurrentTime=DateTime.Now;
如果((CurrentTime.TimeOfDay.Hours==13&&
CurrentTime.TimeOfDay.Minutes==23&&
CurrentTime.TimeOfDay.Seconds==0)&&
NewDayEvent!=null)
{
NewDayEvent(这个,newEventArgs());
}
}
#端区
#区域类方法
私有void OnPropertyChanged([CallerMemberName]字符串成员\u name=”“)
{
if(PropertyChanged!=null)
{
PropertyChanged(此,新PropertyChangedEventArgs(成员名称));
}
}
#端区
#端区
公共会话()
{
Session prevSesh=当前会话;
添加(新会话());
CurrentSession=OpenSessions.Last();
当前_session.addComment(
((TimeEntry)Entries.Last(
x=>x.GetType()==typeof(TimeEntry))
)(数据、评论);
}
}
事件处理程序函数与引发事件的线程在同一线程中执行。问题是,您无法从调度程序线程运行的另一个线程更新UI。您需要在Dispatcher Invoke或BeginInvoke中执行回调函数(或至少是更新部分):
Application.Current.Dispatcher.Invoke(new Action(() => {
//your UI update
}));
你能详细说明一下吗?注释所在的位置是我放置NewDayEvent()的位置吗?或者SplitSession方法代码?两者都可以工作,但在Dispatcher线程中执行事件引发是不合逻辑的,因为这是特定于使用者的行为。因此,您应该将SplitSession内容包装在调用中