Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/321.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何在异步方法中使用来自不同类的其他函数_C#_Wpf_Multithreading - Fatal编程技术网

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()”代码:

  • 在“new MainWindow().Process();”行上, 我收到以下异常:“附加信息:调用线程必须是STA,因为许多UI组件都需要它。” 我已经搜索过了,并且理解了为什么它会给我异常,但是有几个代码对我不起作用

  • 标签没有改变,我知道我正在创建一个新的MainWindow实例,这就是为什么什么都没有显示的原因,但是我正在寻找如何通过使用一个新实例来改变标签的例子

  • 不幸的是,如果没有足够的背景知识,就无法提供准确的答案

    但可以得出一些一般性意见:

  • 最重要的是,如果您需要访问某个类的实例成员,那是因为(或者至少应该是因为……如果该类设计良好,它将始终是这样)您需要使用该类的实例。即,该实例具有您需要访问的状态
  • 因此,仅仅因为您无法访问类的某个实例成员(如这里的
    Process()
    方法)而创建一个类的全新实例总是错误的

    相反,您需要提供对已存在实例的访问,该实例具有您需要访问的状态

  • 根据所提供的代码片段进行粗略猜测,我假设
    ReceiveCallback()
    方法实际上是在
    MainWindow
    类中声明的。如果这个猜测是正确的,那么代码最明显的修复方法就是简单地将
    ReceiveCallback()
    方法设置为非静态的
    static
    。即从方法声明中删除
    static
    。这样做之后,您只需直接调用
    Process()
    ,而不是首先创建
    MainWindow
    的新实例
  • 现在,在这样做的过程中,您可能会(也可能不会)发现,提供方法作为原始I/O操作的参数需要修复。同样,由于您没有提供一个好的代码示例,因此无法说明是否会这样做或如何做。但是我提到它只是为了不让你在从声明中删除
    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..
        }