C# 如何在异步方法中使用来自不同类的其他函数
我对异步非常陌生,我了解一些一般概念,但我似乎无法解决两个问题 我收到以下回电:C# 如何在异步方法中使用来自不同类的其他函数,c#,wpf,multithreading,C#,Wpf,Multithreading,我对异步非常陌生,我了解一些一般概念,但我似乎无法解决两个问题 我收到以下回电: public static void ReceiveCallback(IAsyncResult AR) { Socket CurrentSocket = (Socket)AR.AsyncState; int DataReceived = 0; try { DataReceived = CurrentSocket.End
public static void ReceiveCallback(IAsyncResult AR)
{
Socket CurrentSocket = (Socket)AR.AsyncState;
int DataReceived = 0;
try
{
DataReceived = CurrentSocket.EndReceive(AR);
}
catch (SocketException)
{
CurrentSocket.Close();
return;
}
byte[] receivedBuffer = new byte[DataReceived];
Array.Copy(Buffer, receivedBuffer, DataReceived);
strReceived = Encoding.ASCII.GetString(receivedBuffer); // We are saving the latest receivedBuffer in a string.
new MainWindow().Process(); // We are accessing a function in the MainWindow class
receiveDone.Set();
CurrentSocket.BeginReceive(Buffer, 0, BufferSize, SocketFlags.None, ReceiveCallback, CurrentSocket);
}
下面是“Process()”代码:
Process()
方法)而创建一个类的全新实例总是错误的
相反,您需要提供对已存在实例的访问,该实例具有您需要访问的状态
ReceiveCallback()
方法实际上是在MainWindow
类中声明的。如果这个猜测是正确的,那么代码最明显的修复方法就是简单地将ReceiveCallback()
方法设置为非静态的static
。即从方法声明中删除static
。这样做之后,您只需直接调用Process()
,而不是首先创建MainWindow
的新实例static
后就放弃这个想法
当然,我的猜测可能是错的。在这种情况下,一个选项是提供对
MainWindow
实例的引用,作为I/O操作的状态对象。同样,如果没有一个好的代码示例,不可能说它到底是如何工作的,但基本思想是将它作为最后一个参数传递给Socket.BeginReceive()
方法(任何重载),然后从ReceiveCallback()
方法中的IAsyncResult.AsyncState
属性检索它
注意:以上仅用于解决您遇到的特定异常,因为创建一个新的
MainWindow
实例肯定是错误的。由于I/O操作很可能在UI线程之外完成,因此您仍然存在与处理该操作相关的问题(例如,需要对访问UI本身的代码调用Dispatcher.Invoke()
)。但是一步一个脚印。在继续下一步之前,让我们先解决眼前的问题
如果上述任何一项似乎都没有帮助,那么请修复您的问题,使其包含一个好的代码示例,可以提供实际、准确的答案。提示-请不要在标题中添加标记-根据SOA is状态的规则,
main窗口是一个主窗口,因此它必须是一个且唯一的窗口。只能有一个主窗口。如果您想从异步调用的回调创建窗口,那么您的设计有问题。这是一个糟糕的方法,请重新考虑“创建窗口”?我只是创建一个对象来访问MainWindow类中的函数。Asychnronous方法只是在一个单独的类上创建的。我对AsyncCallback
了解不多,但是状态是“使用AsyncCallback委托在单独的线程中处理异步操作的结果”。听起来你好像在另一个线程中,但不是MainWindowUI线程,它是唯一允许操作UI对象的线程。尝试使用WPF的Dispatcher将代码从回调线程发送到WPF的UI线程。非常感谢您提供的有用信息。您声明我可以删除ReceiveCallback()中的静态。这样做有什么坏处吗?因为如果我没有错的话,根据MSDN,这些回调必须是静态的。我来试试你提到的一些解决办法。谢谢:)编辑:ReceiveCallback()位于程序命名空间中的一个单独类上。每说一句;MainWindow位于MainWindow.xaml.cs中,ReceiveCallback()位于ClientSocket.cs中。显然,在MainWindow类中使用ReceiveCallback()并在ReceiveCallback()方法中删除静态关键字修复了该问题。为了解决线程问题,我使用了以下代码@OhHey:“这些回调必须是静态的”——不确定您在MSDN中看到了什么让您认为是这样的,但这绝对不是真的。回调可以是正确签名的任何委托实例,该委托的目标可以是静态的或非静态的。使用非静态方法没有任何固有的缺点,事实上,使用非静态方法可以更容易地访问实例成员,这是明显的优点。:)彼得,你帮了大忙。再次感谢!
public void Process()
{
lblReceived.Text = ClientSocket.strReceived; // Trying to set what we received in a label..
}