需要帮助。我是Visual Studio C#的新手。 我只用一个按钮和文本框创建一个WINDOWS FORM APPLICATION。基本上我想要做的是运行一个包含oracle块的sql文件,并希望从块生成的输出(dbms_output)显示在文本框中。
直到现在我完成了调用sqlplus并执行该文件并通过消息框检索输出。 但是当我尝试使用文本框执行相同操作时,我会遇到运行时错误。
System.InvalidOperationException未处理 Message =跨线程操作无效:控制'textBox1'从其创建的线程以外的线程访问。 来源= System.Windows.Forms的 堆栈跟踪: 在System.Windows.Forms.Control.get_Handle() 在System.Windows.Forms.Control.set_WindowText(String value) at System.Windows.Forms.TextBoxBase.set_WindowText(String value) 在System.Windows.Forms.Control.set_Text(String value) at System.Windows.Forms.TextBoxBase.set_Text(String value) at System.Windows.Forms.TextBox.set_Text(String value) 在WindowsFormsApplication1.Form1.myProcess_OutputDataReceived(对象 sender,DataReceivedEventArgs e)in C:\ Users \用户sj0087652.TECHMAHINDRA \应用程序数据\本地\临时 Projects \ WindowsFormsApplication1 \ Form1.cs:第22行 at System.Diagnostics.Process.OutputReadNotifyUser(String data) 在System.Diagnostics.AsyncStreamReader.FlushMessageQueue() 在System.Diagnostics.AsyncStreamReader.GetLinesFromStringBuilder() 在System.Diagnostics.AsyncStreamReader.ReadBuffer(IAsyncResult ar) 在System.Runtime.Remoting.Messaging.AsyncResult.SyncProcessMessage(IMessage) MSG) 在System.Runtime.Remoting.Messaging.StackBuilderSink.AsyncProcessMessage(IMessage) msg,IMessageSink replySink) 在System.Runtime.Remoting.Proxies.AgileAsyncWorkerItem.DoAsyncCall() 在System.Runtime.Remoting.Proxies.AgileAsyncWorkerItem.ThreadPoolCallBack(Object O) 在System.Threading.QueueUserWorkItemCallback.WaitCallback_Context(Object 州) at System.Threading.ExecutionContext.Run(ExecutionContext executionContext,ContextCallback callback,Object state,Boolean ignoreSyncCtx) 在System.Threading.QueueUserWorkItemCallback.System.Threading.IThreadPoolWorkItem.ExecuteWorkItem() 在System.Threading.ThreadPoolWorkQueue.Dispatch() 在System.Threading._ThreadPoolWaitCallback.PerformWaitCallback() 的InnerException:
现在我的问题如下:
以下是我的代码:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
void myProcess_OutputDataReceived(object sender, System.Diagnostics.DataReceivedEventArgs e)
{
MessageBox.Show(e.Data);
textBox1.Text += e.Data;
}
void myProcess_Exited(object sender, EventArgs e)
{
MessageBox.Show("Exit");
}
void myProcess_ErrorDataReceived(object sender, System.Diagnostics.DataReceivedEventArgs e)
{
MessageBox.Show("error", e.Data);
}
private void button1_Click(object sender, EventArgs e)
{
myProcess = new System.Diagnostics.Process();
myProcess.StartInfo.FileName = "sqlplus.exe";
myProcess.StartInfo.WorkingDirectory = "";
myProcess.StartInfo.Arguments = "-s hr/hr@XE";
myProcess.StartInfo.RedirectStandardInput = true;
myProcess.StartInfo.RedirectStandardOutput = true;
myProcess.StartInfo.RedirectStandardError = true;
myProcess.StartInfo.UseShellExecute = false;
myProcess.StartInfo.CreateNoWindow = true;
myProcess.OutputDataReceived += new System.Diagnostics.DataReceivedEventHandler(myProcess_OutputDataReceived);
myProcess.ErrorDataReceived += new System.Diagnostics.DataReceivedEventHandler(myProcess_ErrorDataReceived);
myProcess.Exited += new EventHandler(myProcess_Exited);
myProcess.Start();
myProcess.BeginErrorReadLine();
myProcess.BeginOutputReadLine();
myProcess.StandardInput.WriteLine("@C:\\Users\\sj0087652\\Documents\\trial_script.sql");
myProcess.Close();
}
public System.Diagnostics.Process myProcess { get; set; }
}
}
)
答案 0 :(得分:0)
这可能是您最好的选择:
delegate void AddContentDelegate(string Text);
public partial class Form1 : Form
{
AddContentDelegate AddContent;
public Form1()
{
InitializeComponent();
AddContent = new AddContentDelegate(AddContentFunction);
}
void AddContentFunction(string Text)
{
MessageBox.Show(Text);
textBox1.Text += Text + "\r\n";
}
void myProcess_OutputDataReceived(object sender, DataReceivedEventArgs e)
{
BeginInvoke(AddContent, e.Data);
}
void myProcess_Exited(object sender, EventArgs e)
{
MessageBox.Show("Exit");
}
void myProcess_ErrorDataReceived(object sender, DataReceivedEventArgs e)
{
MessageBox.Show("error", e.Data);
}
private void button1_Click(object sender, EventArgs e)
{
myProcess = new System.Diagnostics.Process();
myProcess.StartInfo.FileName = "sqlplus.exe";
myProcess.StartInfo.WorkingDirectory = "";
myProcess.StartInfo.Arguments = "-s hr/hr@XE";
myProcess.StartInfo.RedirectStandardInput = true;
myProcess.StartInfo.RedirectStandardOutput = true;
myProcess.StartInfo.RedirectStandardError = true;
myProcess.StartInfo.UseShellExecute = false;
myProcess.StartInfo.CreateNoWindow = true;
myProcess.OutputDataReceived += new DataReceivedEventHandler(myProcess_OutputDataReceived);
myProcess.ErrorDataReceived += new DataReceivedEventHandler(myProcess_ErrorDataReceived);
myProcess.Exited += new EventHandler(myProcess_Exited);
myProcess.Start();
myProcess.BeginErrorReadLine();
myProcess.BeginOutputReadLine();
myProcess.StandardInput.WriteLine("@C:\\Users\\sj0087652\\Documents\\trial_script.sql");
myProcess.Close();
}
public System.Diagnostics.Process myProcess;
}
BeginInvoke
将在GUI线程上调用该函数(或本例中的Delegate)。您得到的错误是因为它试图跨线程编辑文本框。
您可能希望将其更改为Invoke
,以防止使用弹出框发送垃圾邮件。唯一的区别是Invoke
将等到函数完成后再继续。