我试图在C#中设计类似于Clash of Clans等游戏在构建内容时使用计时器的方式。所以我想了很多,但我真的很难过。
我不确定如何设计这个。我会在.Net Framework中使用Timer类吗?如果是这样的话,API似乎让我有点混淆我如何设置定时器,然后设置第二个定时器,如果我一次构建两个东西(至少在这个例子中)。或者也许有比定时器更好的方法......
为了尽可能直接,我想我问我怎样才能设计一个系统,在点按钮之类的东西之后需要花时间让事情发生?
我想尝试使用控制台应用程序来获取骨架,这样我就可以保持简单。
答案 0 :(得分:1)
我会避免与定时器混在一起 - 他们肯定会完成这项工作,但他们最终会创建大量的事件处理代码,很快就会让人感到困惑。
相反,我会考虑使用Microsoft的Reactive Framework(NuGet“Rx-Main”,“Rx-WPF”或“Rx-WinForms”)来完成您的计时。
以下是您需要的主要方法:
public IObservable<int> Builder(int seconds)
{
var step = 5;
return
Observable
.Generate(
0,
x => x <= 100,
x => x + 5,
x => x,
x => TimeSpan.FromSeconds((double)seconds * (double)step / 100.0));
}
这使您可以创建一个observable,它将为您返回0到100之间的整数,步长为5(您可以更改),并生成总共seconds
秒的值。
这是您用来使用它的代码:
var subscription =
Builder(3)
.Subscribe(
x => Console.WriteLine(x),
() => Console.WriteLine("Done!"));
Console.ReadLine();
您会看到.Subscribe
方法可让您在生成每个值时对其进行响应并获得方便的“完成!”处理程序完成后。
如果您需要在时间用完之前停止订阅 - 例如,如果用户点击取消 - 那么只需在.Dispose()
变量上调用subscription
。
现在,您可能需要将事件编组到UI线程。这很容易做到。假设您正在使用Windows窗体,那么您的代码将如下所示:
var subscription =
Builder(3)
.ObserveOn(someControlOrForm)
.Subscribe(
x => Console.WriteLine(x),
() => Console.WriteLine("Done!"));
这是输出。
0
5
10
15
20
25
30
35
40
45
50
55
60
65
70
75
80
85
90
95
100
Done!
简单。
在评论中,Blindy问为什么这比普通的事件处理程序更好。这是一个例子。
说我有一个我想要更新的图片框列表(List<PictureBox>
),我希望更新有不同的随机时间,我可以这样做:
var query =
from pb in pictureBoxes.ToObservable()
from n in Builder(rnd.Next(2, 6))
select new { pb, n };
var subscription =
query
.ObserveOn(someControlOrForm)
.Subscribe(
x => Console.WriteLine("{0} has value {1}", x.pb, x.n),
() => Console.WriteLine("Done!"));
列表中的所有项目,随机更新,实际上有两行代码。