C# 获取跨线程操作异常
我试图从类内部更新richtextbox,而不是从表单。下面是我的代码:我将表单作为参数传递给客户机类的构造函数C# 获取跨线程操作异常,c#,exception,C#,Exception,我试图从类内部更新richtextbox,而不是从表单。下面是我的代码:我将表单作为参数传递给客户机类的构造函数 public partial class Form1 : Form { public void AppendText(string s) { richtextbox_server_activities.AppendText(s + "\n"); } public Form1() { clien
public partial class Form1 : Form
{
public void AppendText(string s)
{
richtextbox_server_activities.AppendText(s + "\n");
}
public Form1()
{
client = new Client(e.Accepted,e.user,this);
}
//rest of the code of the form
}
以及类“Client”中的函数,我尝试在其中更新gui:
private Form1 form;
public Client(string username, Form1 form)
{
this.form = form;
_baseSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
this.username = username;
}
private void process()
{
int id = pr.ReadInt32();
long index = pr.ReadInt64();
int size = pr.ReadInt32();
byte[] buffer = pr.ReadBytes(size);
TransferQueue queue = _transfers[id];
queue.Write(buffer, index);
queue.Progress = (int)((queue.Transferred * 100) / queue.Length);
if (queue.LastProgress < queue.Progress)
{
queue.LastProgress = queue.Progress;
if (ProgressChanged != null)
{
ProgressChanged(this, queue);
}
if (queue.Progress == 100)
{ //HERE IS WHERE I GET EXCEPTION
this.form.AppendText("Client " + this.username + " has completed uploading the file " + queue.Filename + ".");
queue.Close();
if (Complete != null)
{
Complete(this, queue);
}
}
}
私有表单1表单;
公共客户端(字符串用户名,Form1表单)
{
this.form=形式;
_baseSocket=新套接字(AddressFamily.InterNetwork、SocketType.Stream、ProtocolType.Tcp);
this.username=用户名;
}
私有无效进程()
{
int id=pr.ReadInt32();
长索引=pr.ReadInt64();
int size=pr.ReadInt32();
byte[]buffer=pr.ReadBytes(大小);
TransferQueue队列=_传输[id];
写入(缓冲区、索引);
queue.Progress=(int)((queue.transfer*100)/queue.Length);
if(queue.LastProgress
但是我得到一个错误,说跨线程操作无效:从创建控件的线程以外的线程访问控件。我查看了类似的问题,但仍然得到这个错误。有人看到问题了吗
谢谢问题是您正在使用
客户端
类中的另一个线程访问Form1
控件,您需要调用到正确的线程上
例如:
public void AppendText(string s)
{
Invoke((Action)delegate { richTextBox1.AppendText(s + "\n"); });
}
public Form1()
{
client = new Client(e.Accepted,e.user,AppendText);
}
public class Client
{
private Action<string> _callback;
public Client(string username, Action<string> callback)
{
_callback = callback;
}
private void Process()
{
.......
_callback("Client " + this.username + " has completed uploading the file " + queue.Filename + ".");
}
}
将委托
传递到客户端
而不是整个表单可能是更好的选择
例如:
public void AppendText(string s)
{
Invoke((Action)delegate { richTextBox1.AppendText(s + "\n"); });
}
public Form1()
{
client = new Client(e.Accepted,e.user,AppendText);
}
public class Client
{
private Action<string> _callback;
public Client(string username, Action<string> callback)
{
_callback = callback;
}
private void Process()
{
.......
_callback("Client " + this.username + " has completed uploading the file " + queue.Filename + ".");
}
}
public Form1()
{
客户端=新客户端(e.Accepted,e.user,AppendText);
}
公共类客户端
{
私人行动;
公共客户端(字符串用户名、操作回调)
{
_回调=回调;
}
私有无效进程()
{
.......
_回调(“客户端”+this.username+“已完成上传文件”+queue.Filename+”);
}
}
取决于谁(哪个线程)正在调用process
方法。@UweKeim客户端类中的一个函数调用该过程函数只需确保主UI线程正在更新控件。@panpa它不取决于哪个类中的哪个方法调用该方法。它取决于哪个线程调用它,正如Uwe所说的那样。@panpa现在搜索它。对于或者这个关于在另一个线程中更新UI的异常。谢谢你的回答,我用了另一种方法,它成功了。我遵循了这个链接的说明:如果你使用它,它的作用与传递委托解决方案基本相同,但它会为你调用(它在创建同步上下文时调用任何对象)。我假设.NET3.5是它的winforms,但是如果.NET4.5是,那么这是一个更好的选项,IProgress
通过NuGet包可用于4.0