.net 可以调用并执行引发异常的主UI线程代码吗?
在下面的代码中,我使用进程对象来执行一系列DOS批处理文件。 举个例子,我正在缩短脚本列表 后续(1+)脚本通过事件处理程序(而不是for循环)执行。这样,每个后续脚本仅在前一个脚本完成时运行。现在,由于某种原因,在执行第二个脚本时,我无法获取捕获到的异常以在状态栏中填充错误消息 我正在测试是否在应用程序配置文件中输入了无效的脚本名称,我怀疑我使用的委托不正确。我的匿名委托由“新代码”和现有类方法的组合组成。我认为这是错误的;如果你们能把我推到一个地方,我会很感激的;) 注意:这个.copy_scripts[]是由“goodname.bat,nosuchscript.bat”拆分而成的.net 可以调用并执行引发异常的主UI线程代码吗?,.net,exception,process,delegates,invoke,.net,Exception,Process,Delegates,Invoke,在下面的代码中,我使用进程对象来执行一系列DOS批处理文件。 举个例子,我正在缩短脚本列表 后续(1+)脚本通过事件处理程序(而不是for循环)执行。这样,每个后续脚本仅在前一个脚本完成时运行。现在,由于某种原因,在执行第二个脚本时,我无法获取捕获到的异常以在状态栏中填充错误消息 我正在测试是否在应用程序配置文件中输入了无效的脚本名称,我怀疑我使用的委托不正确。我的匿名委托由“新代码”和现有类方法的组合组成。我认为这是错误的;如果你们能把我推到一个地方,我会很感激的;) 注意:这个.copy_s
我认为,与其使用事件来设置并继续循环,不如使用回调方法创建一个异步委托。流程完成后,只需再次调用
RunCopyScript(…)
。看一看。我肯定有人会用动作
来做这件事,我只是不太清楚,不能给你举个例子
我还看到了一个关于如何将输出从跨线程函数导入gui控件元素的简洁片段。不幸的是,我找不到我之前看到的优雅的代码……如果我遇到它,我会发布一个链接到它
好吧,这就是我所拥有的——为了它的价值。我相信这是相当准确的。我不希望它会开箱即用地编译,因为我没有所有的文件、路径等来正确启动进程。将模拟批处理文件设置为Start()
aProcess
将需要更多的工作。我希望你应该能够与此工作,并有一些更接近你想要的东西,如果交叉引用我上面提供的链接
我还注释掉了一些不需要的代码行,我移动了,或者没有被识别。此外,我没有对您当前的try/catch
块执行任何操作
// same signature as the method to be called asynchronously
delegate void RunScript(Int32 scriptIdx);
// declare IAsyncResult
IAsyncResult result;
Process proc = null;
private void copybutton_Click(object sender , EventArgs e)
{
InitializeBar();
nbr_of_copy_exits_ = 0;
//this.RunCopyScript(this.nbr_of_copy_exits_);
RunScript start = new RunScript(RunCopyScript);
result = start.BeginInvoke(nbr_of_copy_exits_ , new AsyncCallback(CopyExited) , proc);
copybutton.Enabled = false // you don't want the button to be clicked again.
}
private void RunCopyScript(Int32 CopyScriptIdx)
{
try
{
proc = ObtainProcess(client_dest_dir_ + copy_scripts_[CopyScriptIdx]);
proc.EnableRaisingEvents = true;
//proc.Exited += new EventHandler(CopyExited);
proc.Start();
progressBar.Value = ProgressInPercent(copy_scripts_.Count() , CopyScriptIdx);
}
catch (Exception ex)
{
UpdateControl(this.toolStripStatusLabel1, "Error involving " + copy_scripts_[CopyScriptIdx] + ": " +
ex.Message);
copybutton.BackColor = Color.Red;
}
//return;
}
void CopyExited(IAsyncResult iaRes)
{
AsyncResult result = (AsyncResult)iaRes;
RunScript caller = (RunScript)result.AsyncDelegate;
Process senderProcess = (Process)iaRes.AsyncState;
caller.EndInvoke(iaRes);
if (++this.nbr_of_copy_exits_ == this.copy_scripts_.Count())
{
UpdateControl(toolStripStatusLabel1 , "Copying COMPLETE.");
copybutton.Enabled = true; // enable the button now that we're done
}
else
{
// start the process all over again
iaRes = caller.BeginInvoke(this.nbr_of_copy_exits_ , new AsyncCallback(CopyExited) , proc);
}
}
private void UpdateControl(ToolStripStatusLabel tssl , String text)
{
Invoke((MethodInvoker)delegate
{
tssl.Text = text;
progressBar.Value = 0;
});
//tssl.Refresh(); 'System.Windows.Forms.ToolStripStatusLabel' does not contain a definition for 'Refresh'...
}
正如我所说的,有更多优雅的使用动作委托的实现,我确信它们可以是异步的。我希望有人能举个例子。太好了,谢谢你的工作。我试过你的方法,不幸的是得到了同样的结果。但是您的方法使用了我还没有用到的东西:Begin/EndInvoke、委托定义、IAsync等等。我相信很快就会用到它们。谢谢。@Joe:我不确定我能帮到你有多近,但我认为这可能值得一试。这绝对是值得的。我将用一个尚未解决的小问题(即,应用程序配置文件一开始不太可能更改,更不用说其中有无效条目)来换取一种新的处理方式。这是我绝对会使用的好信息。我们“自欺欺人”需要团结一致。这并不容易,不是吗;)
// same signature as the method to be called asynchronously
delegate void RunScript(Int32 scriptIdx);
// declare IAsyncResult
IAsyncResult result;
Process proc = null;
private void copybutton_Click(object sender , EventArgs e)
{
InitializeBar();
nbr_of_copy_exits_ = 0;
//this.RunCopyScript(this.nbr_of_copy_exits_);
RunScript start = new RunScript(RunCopyScript);
result = start.BeginInvoke(nbr_of_copy_exits_ , new AsyncCallback(CopyExited) , proc);
copybutton.Enabled = false // you don't want the button to be clicked again.
}
private void RunCopyScript(Int32 CopyScriptIdx)
{
try
{
proc = ObtainProcess(client_dest_dir_ + copy_scripts_[CopyScriptIdx]);
proc.EnableRaisingEvents = true;
//proc.Exited += new EventHandler(CopyExited);
proc.Start();
progressBar.Value = ProgressInPercent(copy_scripts_.Count() , CopyScriptIdx);
}
catch (Exception ex)
{
UpdateControl(this.toolStripStatusLabel1, "Error involving " + copy_scripts_[CopyScriptIdx] + ": " +
ex.Message);
copybutton.BackColor = Color.Red;
}
//return;
}
void CopyExited(IAsyncResult iaRes)
{
AsyncResult result = (AsyncResult)iaRes;
RunScript caller = (RunScript)result.AsyncDelegate;
Process senderProcess = (Process)iaRes.AsyncState;
caller.EndInvoke(iaRes);
if (++this.nbr_of_copy_exits_ == this.copy_scripts_.Count())
{
UpdateControl(toolStripStatusLabel1 , "Copying COMPLETE.");
copybutton.Enabled = true; // enable the button now that we're done
}
else
{
// start the process all over again
iaRes = caller.BeginInvoke(this.nbr_of_copy_exits_ , new AsyncCallback(CopyExited) , proc);
}
}
private void UpdateControl(ToolStripStatusLabel tssl , String text)
{
Invoke((MethodInvoker)delegate
{
tssl.Text = text;
progressBar.Value = 0;
});
//tssl.Refresh(); 'System.Windows.Forms.ToolStripStatusLabel' does not contain a definition for 'Refresh'...
}