为什么不能'

本文关键字:不能 为什么 | 更新日期: 2023-09-27 17:53:53

你好,我想从一个函数中调用一个子程序,但这似乎是不可能的:

private static void onEnergyTimer(object source, ElapsedEventArgs e)
    {
        if (energy < pastEnergy - 20) {
            StartCoroutine(SendData());}
}

作为一种工作,我尝试了这个,但是当我尝试下面的代码时,我得到了错误"在类,结构或接口成员声明中意外的符号void"

using System;
using System.Collections;
using System.Collections.Generic;
using System.Timers; 
using UnityEngine;
public class StickTimerBetaCoroutine2 : MonoBehaviour
{
        public static float energy = 50.0f;
        private static float pastEnergy = energy;
        public void Update ()
        {
                System.Timers.Timer energyTimer = new System.Timers.Timer ();
                energyTimer.Elapsed += new ElapsedEventHandler (onEnergyTimer);
                energyTimer.Interval = 3000;
                energyTimer.Enabled = true;
                {
                        if (JoeysInputStick.flex <= 0) {
                                energy -= 8 * (Time.deltaTime);
                        } else if (JoeysInputStick.flex >= 1) {
                                energy += 2;
                        } else if (JoeysInputStick.flex >= 2) {
                                energy += 5;
                        } else if (JoeysInputStick.flex >= 3) {
                                energy += 7;
                        } else if (JoeysInputStick.flex >= 4) {
                                energy += 9;
                        } else if (JoeysInputStick.flex >= 5) {
                                energy += 11;
                        } else if (JoeysInputStick.flex >= 6) {
                                energy += 13;
                        }
                }
                energy = Mathf.Clamp (energy, 0.0F, 600.0F); 
                RectTransform rTrans = (RectTransform)transform.GetComponent<RectTransform> ();
                rTrans.sizeDelta = new Vector2 (200, energy);   
        }   
        private async void onEnergyTimer (object source, ElapsedEventArgs e)
        {
                if (energy < pastEnergy - 20) {
                        JoeysInputStick.SendTensOn ();
                        await Task.Delay (800);
                        JoeysInputStick.SendTensOff ();
                }
                pastEnergy = energy;
        }
}

为什么不能'

删除异步关键字

你不应该在这个函数上使用async关键字。Elapsed timer事件没有在寻找Async方法。

看起来你想直接引用已经存在的private static void onEnergyTimer。我假设您使用反编译器(ilspy或其他)获得了该代码片段,并且无法更改该代码。

为什么async不能在事件处理程序上工作

事件处理程序通常不支持/期望调用异步方法。我不确定,但我认为你正在使用的一个使用Windows消息泵队列的消息动作经过的信号。Windows消息泵的存在使得所有UI交互都发生在拥有控制句柄的主线程上。

异步模式不适合计时器。相反,如果你确实想要一个async等效的延迟,你可以将Update函数标记为async,然后不使用Timer和Elapsed函数,你可以添加这样的行:

            await Task.Delay(3000); //Here's your delay
            if (energy < pastEnergy - 20) {
                    JoeysInputStick.SendTensOn ();
                    await Task.Delay (800);
                    JoeysInputStick.SendTensOff ();
            }
            pastEnergy = energy;

标记第三方onEnergyTimer函数为Public

与其实现自己可访问的onEnergyTimer函数,不如编辑第三方DLL(大概),将函数更改为public。有很多方法可以做到这一点,一个是要求第三方更新他们对该函数的可访问性,另一个技术解决方案是使用Mono Cecil库(如果需要,我可以更详细地介绍,请留下评论)-如果您可以控制升级的dll,并且如果您确实希望他们的版本保持一致性,这将是最好的方法。

您试图将您的方法签名放在任何类之外,编译器期望您声明一个类、结构或接口。把你的方法移到你的类里面。

public class MyClass
{
    ...
    private async void onEnergyTimer(object source, ElapsedEventArgs e)
    {
        if (energy < pastEnergy - 20) {
            JoeysInputStick.SendTensOn();
            await Task.Delay(800);
            JoeysInputStick.SendTensOff();
        }
        pastEnergy = energy;
    }
}

这个错误经常发生,因为你的大括号没有正确匹配。如果你认为你的方法是在你的类中声明的,检查你的大括号,看看你是否有一个关闭大括号},你不是故意的。

我得到了一些帮助,事实证明这个问题是由编辑器(mono development)和Unity(游戏引擎)使用的。net版本引起的。我无法改变这些因素中的任何一个,所以我们使用下面的代码作为解决方案:

private Queue energyQueue = new Queue();
        private bool tensInAction = false;
        private void onEnergyTimer (object source, ElapsedEventArgs e)
        {
            float maxEnergy = 0;
            foreach (System.Object reading in (IEnumerable) energyQueue) {
                if ((float) reading > maxEnergy) {
                    maxEnergy = (float) reading;
                }
            }
            if (energy < maxEnergy - 20 && !tensInAction) {
                energyQueue.Clear();
                tensInAction = true;
                JoeysInputStick.SendTensOn ();
                System.Timers.Timer tensTimer = new System.Timers.Timer ();
                tensTimer.Elapsed += new ElapsedEventHandler (onTensTimer);
                tensTimer.Interval = 800;
                tensTimer.Enabled = true;
            }
            energyQueue.Enqueue(energy);
            if (energyQueue.Count > 12) {
                energyQueue.Dequeue();
            }
        }
    private void onTensTimer (object source, ElapsedEventArgs e) {
            JoeysInputStick.SendTensOff ();
            tensInAction = false;
        }