c# - 我的代码是否以正确的顺序执行?
问题描述
我有以下代码,我希望它以正确的顺序执行,但我不确定我是否正确使用“等待”以便它以正确的顺序执行。
正确的顺序应该是:
1) 调用 GetTiltleData 并获取 CurrentCatalogVersion。
2) 调用 GetCatalogData 以获取将要购买的商品的 ItemID。
3) 致电 MakePurchase 购买商品。
4)调用GetInventoryList获取玩家当前(购买后)的库存。
我是否正确使用等待?我的代码是否以正确的顺序执行,或者代码是否可能以错误的顺序执行?
例如,GetCatalogData(); 的代码是否可能?在 CurrentCatalogVersion = result.Result.Data["Catalogversion"]; 之前执行 ?
string CurrentCatalogVersion = "";
string ItemID = "";
int CurrentAmount = 0;
GetTiltleData();
GetCatalogData();
public async void GetTiltleData()
{
await ClientGetTitleData();
}
private async Task ClientGetTitleData()
{
var result = await PlayFabClientAPI.GetTitleDataAsync(new GetTitleDataRequest());
if (result.Result.Data == null || !result.Result.Data.ContainsKey("Catalogversion"))
Console.WriteLine(result.Error.GenerateErrorReport());
else
CurrentCatalogVersion = result.Result.Data["Catalogversion"];
}
public async void GetCatalogData()
{
await GetCatalog();
}
private async Task GetCatalog()
{
var result = await PlayFabClientAPI.GetCatalogItemsAsync(new GetCatalogItemsRequest()
{
CatalogVersion = CurrentCatalogVersion
});
foreach (var entry in result.Result.Catalog)
{
//For example, if you want to purchase a sword
if (entry.DisplayName == "Sword")
ItemID = entry.ItemId;
}
if (result.Error != null)
{
Console.WriteLine(result.Error.GenerateErrorReport());
}
else
{
Console.WriteLine("Listed items successful!");
await MakePurchase(ItemID);
}
}
private async Task MakePurchase(string itemid)
{
var result = await PlayFabClientAPI.PurchaseItemAsync(new PurchaseItemRequest()
{
CatalogVersion = CurrentCatalogVersion,
ItemId = ItemID,
Price = 100,
VirtualCurrency = "GO"
});
if (result.Error != null)
{
Console.WriteLine(result.Error.GenerateErrorReport());
}
else
{
Console.WriteLine("Purchase successful!");
await GetInventoryList();
}
}
private async Task GetInventoryList()
{
var result = await PlayFabClientAPI.GetUserInventoryAsync(new GetUserInventoryRequest());
//Get the current amount of the player's virtual currency after the purchase
CurrentAmount = result.Result.VirtualCurrency["GO"];
foreach (var entry in result.Result.Inventory)
{
//Get a list with the player's items after the purchase
Console.WriteLine($"{entry.DisplayName} {entry.UnitPrice} {entry.ItemId} {entry.ItemInstanceId}");
...
}
if (result.Error != null)
{
// Handle error if any
Console.WriteLine(result.Error.GenerateErrorReport());
}
else
{
Console.WriteLine("Got current inventory");
}
}
解决方案
例如,GetCatalogData(); 的代码是否可能?在 CurrentCatalogVersion = result.Result.Data["Catalogversion"]; 之前执行 ?
是的,一点没错。
这是您的调用代码:
...
GetTiltleData();
GetCatalogData();
这些是异步方法,但在继续下一条指令之前,您无需等待它们的结果。这意味着这两种方法都是触发并忘记线程。
这意味着你有一个竞争条件。从字面上看,您有 2 个线程竞相在另一个之前完成它们的方法。您无法保证哪个会先完成,或者 CPU 将如何优先处理它们的指令。由于您调用这些方法的方式,您基本上已经告诉计算机您不关心事件的结果。
确保一种方法在下一种方法开始之前完成的最快方法是对await
它们都适用。正如Igor所说,如果您要使用异步方法,则应该在调用堆栈上下的整个过程中使用 async/await。
string CurrentCatalogVersion = "";
string ItemID = "";
int CurrentAmount = 0;
await GetTiltleData(); // adding "await" to these 2 lines
await GetCatalogData();
此外,请不要async void
在您的方法签名中使用。你应该async Task
改用。请参阅async/await - 何时返回 Task vs void?.
推荐阅读
- spring-boot - JPA/休眠。如何使用 createQuery 方法获取包含在父对象列表中的子对象
- c# - 使用 .p12 验证端点
- css - 如何申请 CSS Modules 的条件?
- xml - 带有数字的 xml 标记
- regex - 在雪花中查找具有重复模式的字符串
- javascript - 在 UWP WebView 中显示本地 html 页面
- java - 在 android 中使用 Bundle 类在活动之间传递信息有什么意义吗?
- microsoft-teams - 当 Zoom 或 MSTeams 桌面客户端运行时(打开摄像头),MediaDevices.getUserMedia 在 Windows 上引发异常
- python - 如何在 Sympy 中的多个方程中替换变量
- typescript - 如何以可用的方式重新导出具有接口的导入模块?