'C# Async deadlock
I am having trouble with a deadlock in C# using an async method from an external library. I am reasonably new to async programming so it's possible I have missed something very obvious here. The library I have been using is nethereum and the following code will hang without throwing any errors and I don't know how to debug it.
public Account(Wallet wallet, string name = "") //This is a constructor so it can't be async.
{
Console.WriteLine("########################################################## Starting Account Constructor");
Task.Run(async () => await GetTokens()); //If I change this to a .wait() it will hang one call earlier at TokenListService
Console.WriteLine("########################################################## Finishing Account Constructor");
}
public async Task GetTokens()
{
Console.WriteLine("########################################################## Starting Account GetTokens");
Web3 web3 = new Web3(Globals.web3Endpoint);
Console.WriteLine("########################################################## Starting Account LoadFromUrl");
var tokens = await new TokenListService().LoadFromUrl(TokenListSources.UNISWAP);
Console.WriteLine("########################################################## Starting Account GetAllTokenBalancesUsingMultiCallAsync");
//Hangs here
var tokensOwned = await web3.Eth.ERC20.GetAllTokenBalancesUsingMultiCallAsync(
new string[] { privateKey }, tokens.Where(x => x.ChainId == 1),
BlockParameter.CreateLatest());
//This never runs
Console.WriteLine("########################################################## Starting Account GetTotalBalance");
}
Additionally to the above the code works when I run it in a stand alone console application. The below example should run fine.
namespace testProj
{
class Program
{
public static async Task GetERC20Balances()
{
var web3 = new Web3(“<endpoint>”);
var tokens = await new TokenListService().LoadFromUrl(TokenListSources.UNISWAP);
var owner = “<account address>”;
var tokensOwned = await web3.Eth.ERC20.GetAllTokenBalancesUsingMultiCallAsync(
new string[] { owner }, tokens.Where(x => x.ChainId == 1),
BlockParameter.CreateLatest());
Console.WriteLine(“This works…”);
}
static void Main()
{
GetERC20Balances().Wait();
Console.WriteLine("Finished!");
Console.ReadLine();
}
}
}
How would I go about debugging this deadlock?
Solution 1:[1]
It looks like you're using dart with null safety on and you are accessing a list or map that might be null. It's hard to tell from your code, but I'm guessing the offending line is
questionModel.correctOption = questionSnapshot.data()["option1"];
It might be one of the other [] calls earlier in your code (such as
questionSnapshot.data()["option1"]
), but the solution is the same.
The problem is that questionSnapshot.data() might return null, and the compiler is flagging it.
If you are sure the data is not null, you can use the !
operator, like this:
questionModel.correctOption = questionSnapshot.data()!["option1"];
Another solution is a conditional null-safe operator ?
, with a default value. In this case, the code would look like this:
questionModel.correctOption = questionSnapshot.data()?["option1"]??"DefaultValue;
But I would recommend checking if the returned data is null. It's easier for others to read and can be logged more easily:
var data = questionSnapshot.data();
if (data != null) {
questionModel.correctOption = data["option1"];
}
else {
//do something in that case
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Paul |