为什么不能'
本文关键字:不能 为什么 | 更新日期: 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;
}