我正在构建一个Tic-Tac_toe api游戏。游戏工作正常,直到其中一个玩家按下一个完成游戏的广场(他赢了或填满了棋盘)。
当我为最后一次移动启用所有CLR例外时,这是我在第var user = await UserManager.FindByIdAsync(userId);
行看到的例外
“附加信息:在上一个异步操作完成之前,在此上下文中启动了第二个操作。使用'await'确保在此上下文上调用另一个方法之前已完成任何异步操作。任何实例成员都不能保证是线程安全“。
重要知道玩家何时点击一个正方形,这是一个'POST'方法。 这是我的代码:
public class GamesApiController : ApiController
{
ApplicationDbContext context = new ApplicationDbContext();
private ApplicationUserManager _userManager;
public IEnumerable<ApplicationUser> Get()
{
return context.Users;
}
public ApplicationUserManager UserManager
{
get
{
return _userManager ?? System.Web.HttpContext.Current.Request.GetOwinContext().GetUserManager<ApplicationUserManager>();
}
private set
{
_userManager = value;
}
}
#region Methods
/// <summary>
/// update the server data by reciving the model and square and returns the new model
/// </summary>
/// <param name="_model"></param>
/// <param name="squareId"></param>
/// <returns></returns>
//square clicked via post
[Route("api/gamesapi/{squareId}")]
public async Task<HttpResponseMessage> Post([FromBody]GameModel model, int squareId)
{
HttpResponseMessage response;
if (model == null)
{
//Utilites.CreateMsgCookie(Response, "Error", "Sorry, an unknown error has occurred");
response = Request.CreateErrorResponse(HttpStatusCode.NotFound, "model wasn't found");
return response;
}
//GameModel model = JsonConvert.DeserializeObject<GameModel>(_model);
Game game = GetGameById(model.Game.GameId);
if (game == null)
{
response = Request.CreateErrorResponse(HttpStatusCode.NotFound, "game wasn't found");
}
else
{
if (game.UserIdTurn == game.User1Id) //pressing user is user1
{
ChangeSquareState(game, squareId, true);
game.UserIdTurn = game.User2Id;
}
else //game.UserIdTurn == game.User2Id - pressing user is user2
{
ChangeSquareState(game, squareId, false);
game.UserIdTurn = game.User1Id;
}
SquareState[] board = new SquareState[] {game.Square1,game.Square2,game.Square3,game.Square4,
game.Square5,game.Square6,game.Square7,game.Square8,game.Square9};
if (didPlayerWin(board))
{
game.WinnerId = model.User.Id;
await UpdateUserGameState(1, game.User1Id);
await UpdateUserGameState(2, game.User2Id);
game.IsGameOver = true;
}
else
{
bool isBoardFull = true;
for (int i = 0; i < board.Length; i++)
{
if (board[i] == SquareState.Blank)
{
isBoardFull = false;
break;
}
}
if (isBoardFull)
{
await UpdateUserGameState(3, game.User1Id);
await UpdateUserGameState(3, game.User2Id);
game.IsGameOver = true;
}
}
context.SaveChanges();
response = Request.CreateResponse(HttpStatusCode.OK, game);
}
return response;
}
/// <summary>
/// When a game is over, recive a gameState and update the user. 1 for a win, 2 for loss, 3 for aa draw
/// </summary>
/// <param name="gameState"></param>
private async Task UpdateUserGameState(int gameState, string userId)
{
var user = await UserManager.FindByIdAsync(userId);
switch (gameState)
{
case 1:
user.GamesWon++;
break;
case 2:
user.GamesLost++;
break;
case 3:
user.GamesDraw++;
break;
default:
break;
}
UserManager.UpdateAsync(user);
}
[HttpGet]
[Route("api/gamesapi/{gameId}")]
/// <summary>
/// method to bring the latest game's state from the context and send it back in a GameModel
/// </summary>
/// <param name="_model"></param>
/// <returns></returns>
public HttpResponseMessage Get(int gameId)
{
HttpResponseMessage response;
Game game = GetGameById(gameId);
if (game == null)
{
response = Request.CreateErrorResponse(HttpStatusCode.NotFound, "game wasn't found");
}
else
{
response = Request.CreateResponse(HttpStatusCode.OK, game);
}
return response;
}
/// <summary>
/// method that check if the board have a line(3 squars in a row)
/// of the same element of user1 or user2 , defult - returns fault
/// </summary>
/// <param name="board"></param>
/// <returns></returns>
private bool didPlayerWin(SquareState[] board)
{
}
/// <summary>
/// change the SquareState of a specific square of the sent game according to the pressing user
/// </summary>
/// <param name="game"></param>
/// <param name="SquareId"></param>
/// <param name="_isUser1"></param>
private void ChangeSquareState(Game game, int SquareId, bool _isUser1)
{
}
/// <summary>
/// get game from context by gameId , Defult result - null
/// </summary>
/// <param name="gameId"></param>
/// <returns></returns>
private Game GetGameById(int gameId)
{
}
#endregion
}
答案 0 :(得分:0)
我认为您错过了等待UpdateUserAsync()
方法中的UpdateUserGameState()
:
private async Task UpdateUserGameState(int gameState, string userId)
{
var user = await UserManager.FindByIdAsync(userId);
// ...
// add missing await
await UserManager.UpdateAsync(user);
}