SampleLockService.cs 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. using System;
  2. using DeepCrystal.RPC;
  3. using DeepMMO.Protocol;
  4. using System.Threading.Tasks;
  5. namespace CommonRPG.Server.Sample
  6. {
  7. public class SampleLockService : IService
  8. {
  9. //消耗硬币的服务
  10. IRemoteService machine;
  11. //硬币数量
  12. int coinCount;
  13. //硬币锁
  14. IAsyncLock coinLocker;
  15. public override ServiceProperties Properties
  16. {
  17. get
  18. {
  19. var basep = base.Properties;
  20. // 允许并发
  21. basep.IsConcurrent = true;
  22. return basep;
  23. }
  24. }
  25. public SampleLockService(ServiceStartInfo start) : base(start) {
  26. }
  27. protected override void OnDisposed()
  28. {
  29. //销毁锁
  30. this.coinLocker.Dispose();
  31. }
  32. protected override async Task OnStartAsync()
  33. {
  34. //创建异步锁(内存)
  35. this.coinLocker = Provider.CreateLock();
  36. //获得消耗者
  37. this.machine = await this.Provider.GetAsync(new RemoteAddress("Machine"));
  38. }
  39. protected override Task OnStopAsync(ServiceStopInfo stop)
  40. {
  41. return Task.CompletedTask;
  42. }
  43. //----------------------------------------------------------------------------------------------
  44. //----------------------------------------------------------------------------------------------
  45. // Async 异步写法
  46. [RpcHandler(typeof(PlayGameRequest), typeof(PlayGameResponse))]
  47. public async Task<PlayGameResponse> rpc_PlayGameAsync(PlayGameRequest req)
  48. {
  49. // <--- 此处如果不加锁,假如同时两个PlayGameRequest过来,则可能会导致coinCount为负数
  50. using (await this.coinLocker.LockAsync())
  51. {
  52. //判断硬币数量够不够
  53. if (coinCount > req.count)
  54. {
  55. //异步调用
  56. var rsp = await machine.CallAsync<PlayGameResponse>(req);
  57. //消耗硬币
  58. coinCount -= rsp.usedCoin;
  59. //返回结果
  60. return rsp;
  61. }
  62. //返回失败结果
  63. return new PlayGameResponse() { s2c_code = Response.CODE_ERROR };
  64. }
  65. }
  66. //----------------------------------------------------------------------------------------------
  67. // Promise 写法,等同于 rpc_PlayGameAsync
  68. [RpcHandler(typeof(PlayGameRequest), typeof(PlayGameResponse))]
  69. public void rpc_PlayGame(PlayGameRequest req, OnRpcReturn<PlayGameResponse> callback)
  70. {
  71. // <--- 此处如果不加锁,假如同时两个PlayGameRequest过来,则可能会导致coinCount为负数
  72. this.coinLocker.LockAsync().ContinueWith((_lock)=>
  73. {
  74. //判断硬币数量够不够
  75. if (coinCount > req.count)
  76. {
  77. //异步调用,消耗硬币
  78. machine.Call<PlayGameResponse>(req, new OnRpcReturn<PlayGameResponse>((rsp, err) =>
  79. {
  80. //消耗硬币
  81. coinCount -= rsp.usedCoin;
  82. //返回结果
  83. callback(rsp);
  84. _lock.Dispose();
  85. }));
  86. }
  87. else
  88. {
  89. //返回失败结果
  90. callback(new PlayGameResponse() { s2c_code = Response.CODE_ERROR });
  91. _lock.Dispose();
  92. }
  93. });
  94. }
  95. //----------------------------------------------------------------------------------------------
  96. }
  97. public class PlayGameRequest : Request
  98. {
  99. public int count;
  100. }
  101. public class PlayGameResponse : Response
  102. {
  103. public int usedCoin;
  104. }
  105. }