我有一个应用程序,其中我希望在触发事件时在同一个线程中执行一个函数。例如:
SomeCode()
{
// Do something...
// Fire event to run SomeOtherCode().
}
SomeOtherCode()
{
// Do something else...
}
我不想简单地调用该函数,因为它会保留它。 SomeOtherFuction()
需要在同一个线程中执行,因为它需要访问表单控件,我需要它从事件触发器触发开始执行。我使用的是Microsoft Visual C#2008 Express Edition。感谢。
:::编辑::: 其他细节:最重要的是,我的表单应用程序的控制器花了太长时间才完成,并且从用户启动应用程序到应用程序窗口出现在显示器上时,它导致了显着的延迟。这在较快的计算机上不是问题,但在较慢的计算机上,这是一个大问题。我需要尽快退出控制器,从而允许框架绘制应用程序窗口,并在构造函数外继续初始化。 (所有基本项目仍将在构造函数中初始化。)
事件触发的函数调用将是理想的。我宁愿不使用计时器。将受影响的代码与Invoke交错在我的情况下是不切实际的,并且需要更多的时间来实现,而不是我必须处理这个问题。 一个简单的事件驱动函数调用示例就是我真正想要的。感谢。
答案 0 :(得分:1)
从您的帖子看,您似乎对一些问题感到困惑。 .Net中的标准模式是事件同步运行。以下几行在执行时基本相同。
选项#1
SomeCode();
SomeOtherCode();
选项#2
SomeEvent += delegate { SomeOtherCode(); }
...
SomeCode();
SomeEvent(this,EventArgs.Empty);
如果要取消阻止UI线程并稍后运行代码,则需要使用某种机制来延迟SomeOtherCode
函数的运行。在WinForms应用程序中执行此操作的最简单方法是使用WinForms Timer实例。这将在稍后的时间点在UI线程上引发一个您可以响应的事件。在此期间,它也不会阻止UI线程,从而允许表单继续处理。
答案 1 :(得分:0)
您似乎要求稍后运行SomeOtherCode()
。
您可以调用BeginInvoke
(来自UI线程或任何其他线程)将函数排入队列以在下一个消息循环中运行:
BeginInvoke(new Action(SomeOtherCode));
答案 2 :(得分:0)
似乎您希望向暴露SomeCode方法的类添加事件。然后,实现SomeOtherCode方法的类将附加一个调用SomeOtherCode方法的事件处理程序。
在一个类中完成此操作是完全可行的,以防您有某种状态模型,您希望根据其他逻辑添加/删除调用。
答案 3 :(得分:0)
我认为您希望将SomeOtherCode
放入Task
或BackgroundWorker
,然后与UI线程同步以向其发送更新。
我最近发布了on my blog a class,这使得从Task
更新UI与从BGW一样简单。我建议使用Task
而不是BackgroundWorker
。
答案 4 :(得分:0)
Simialr对Stephen的说法,我建议您将尽可能多的初始化代码移动到后台线程或任务。让后台线程尽可能多地工作,然后通过Action<>'将必要的窗口更新发送到您的UI线程。这是一些快速的伪样本代码:
protected void LoadMyListInBackground(object state)
{
List<string> myList = Databse.FetchMyList(myParameters); // This take a while, so the UI thread isn't waiting
ShowMyList(myList);
}
protected void ShowMyList(List<string> theList)
{
if(InvokeRequired)
Invoke(new Action<List<string>>(ShowMyList, theList);
else
{
foreach(string item in theList)
myListBox.Items.Add(item);
}
}
在此示例中,UI线程可以自由地绘制窗口,而后台线程可以执行冗长的数据库工作。问题是,即使您在构造函数之外触发事件,并且该事件发生在UI线程上并且需要很长时间,用户可能会看到窗口,但该窗口将“冻结”并且可能看起来像'坠毁'给用户。这种技术可以防止这种情况,并提供更好的用户体验。