C
C#ā€¢6mo ago
VerpinZal

Auto-translation, HttpClient, Result, await...

This is my code inside an application for translation purposes. It queries the user's OS for the installed language, retrieves the two letter ISO language code, sends it to google along with strings and displays the translated text. However, only in debug mode, this code sometimes throws an access violation reading location exception at "var result" line. I know why that is, because Result is running async and it's blocking the thread until Result is retrieved. Solution appears to be converting the entire method to async Task<string>. Problem is, I racked my brains to find a way to convert Task<string> to string, to no avail. I've been tinkering with just this method intermittently for two weeks now and I'm at my wit's end. Could a kind soul at least provide me with some hints or point to the right direction? I change the code as var result = await HttpClient.GetStringAsync(url); and the code builds. How do I proceed then? What's the right method to call this function so it displays the right strings instead of System.Task.Task`f or the like? Thanks a million.
public string TranslateText(string input, string twoLetterIsolanguageCode)
{

if (CheckForInternetConnection())
{
string url = String.Format
("https://translate.googleapis.com/translate_a/single?client=gtx&sl={0}&tl={1}&dt=t&q={2}",
"en",
twoLetterIsolanguageCode,
Uri.EscapeUriString(input));

HttpClient httpClient = new HttpClient();
var result = httpClient.GetStringAsync(url).Result;

var jsonData = new JavaScriptSerializer().Deserialize<List<dynamic>>(result);

var translationItems = jsonData[0];

string translation = "";

foreach (object item in translationItems)
{
IEnumerable? translationLineObject = item as IEnumerable;

IEnumerator translationLineString = translationLineObject.GetEnumerator();

translationLineString.MoveNext();

translation += string.Format(" {0}", Convert.ToString(translationLineString.Current));
}

if (translation.Length > 1) { translation = translation.Substring(1); };

return translation;

}
else
{
return input;
}


}
public string TranslateText(string input, string twoLetterIsolanguageCode)
{

if (CheckForInternetConnection())
{
string url = String.Format
("https://translate.googleapis.com/translate_a/single?client=gtx&sl={0}&tl={1}&dt=t&q={2}",
"en",
twoLetterIsolanguageCode,
Uri.EscapeUriString(input));

HttpClient httpClient = new HttpClient();
var result = httpClient.GetStringAsync(url).Result;

var jsonData = new JavaScriptSerializer().Deserialize<List<dynamic>>(result);

var translationItems = jsonData[0];

string translation = "";

foreach (object item in translationItems)
{
IEnumerable? translationLineObject = item as IEnumerable;

IEnumerator translationLineString = translationLineObject.GetEnumerator();

translationLineString.MoveNext();

translation += string.Format(" {0}", Convert.ToString(translationLineString.Current));
}

if (translation.Length > 1) { translation = translation.Substring(1); };

return translation;

}
else
{
return input;
}


}
13 Replies
Denis
Denisā€¢6mo ago
You do not convert Task<T> to T. You await the task to get T So your method must also be async
public async Task<string> TranslateTextAsync(......)
{
.......

var result = await httpClient.GetStringAsync(url);
.....
}
public async Task<string> TranslateTextAsync(......)
{
.......

var result = await httpClient.GetStringAsync(url);
.....
}
And oh boy I see dynamic. You sure there isn't a better way? Given that the api is returning JSON, you probably want to use System.Text.Json and deserialize to a C# model Or you can use newtonsoft json instead Avoid dynamic. You shouldn't be using it, unless you are dealing with COM
Denis
Denisā€¢6mo ago
Asynchronous programming scenarios - C#
Learn about the C# language-level asynchronous programming model provided by .NET Core.
VerpinZal
VerpinZalā€¢6mo ago
I will look into all of the things mentioned, thank you very much!
Denis
Denisā€¢6mo ago
Are you sure the access violation isn't because of attempting to access a member of a dynamic object, which is not there? *disclaimer, I do not know this exception by heart
VerpinZal
VerpinZalā€¢6mo ago
it's GdiPlus.dll exception, access violation at reading address 0x0000000000
VerpinZal
VerpinZalā€¢6mo ago
No description
Denis
Denisā€¢6mo ago
What in the world And now we pray Gdi stuff is generally UI related
VerpinZal
VerpinZalā€¢6mo ago
To be perfectly honest, i get the same error while trying to retrieve the process name that launched the application, but that's another story
Denis
Denisā€¢6mo ago
And you'd usually see it in a winform app
VerpinZal
VerpinZalā€¢6mo ago
this is a winform app šŸ˜„
Denis
Denisā€¢6mo ago
Ahaaa There might be more to your issue than meets the eye
VerpinZal
VerpinZalā€¢6mo ago
probably i'll do some reading apparently no reading documentation is enough thanks a million!
Denis
Denisā€¢6mo ago
I recommend going with wpf You won't get any obscure gdi errors Proper wpf will require some mvvm knowledge, but you can survive without it for the time being Are you creating UI components based on the loaded data?