Good day to all.

Not so long ago I started programming in C #. As a result, wrote the following: DIPlaylist - the program creates a DI.FM playlist for AIMP with activated premium for 7 days.

Since I study on my own, I cannot evaluate the correctness of the code. For the first time, I used async / await to ensure that the main tasks were performed outside the main thread, thereby preventing the main window of the program from hanging. But in the current form, I sometimes notice that it does happen.

As a result, I had a question, did I use async / await correctly? I will also be very grateful for comments on the rest of the code, it will be extremely useful for my training.

The code is small and in it I tried to comment on all significant and perhaps incomprehensible at first glance moments.

An example of such a code (clippings):

private async void btnStart_Click(object sender, RoutedEventArgs e) { progressBar.Value++; // ΠŸΠΎΠ»ΡƒΡ‡Π΅Π½ΠΈΠ΅ письма с ΠΏΡ€Π΅ΠΌΠΈΡƒΠΌ-ссылкой statusLabel.Content = await TempMail.GetLetter(); if (String.IsNullOrEmpty(Settings.TmLetterID)) { Status(false); return; } progressBar.Value++; // Π‘ΠΎΠ·Π΄Π°Π½ΠΈΠ΅ ΠΈ сохранСниС плСйлиста statusLabel.Content = await Playlist.GoPlaylist(); if (statusLabel.Content.ToString().ToLower().Contains("ошибка")) { Status(false); return; } } public static async Task<string> GetLetter() { SetHeader(); // 10 ΠΏΠΎΠΏΡ‹Ρ‚ΠΎΠΊ с Π·Π°Π΄Π΅Ρ€ΠΆΠΊΠΎΠΉ Π² 3 сСкунды Π½Π° ΠΏΠΎΠ»ΡƒΡ‡Π΅Π½ΠΈΠ΅ письма for (int i = 0; i < 10; i++) { await Task.Run(() => { Thread.Sleep(3000); }); string responseBody = ""; try { HttpResponseMessage response = await httpClient.GetAsync(Settings.TmURL); responseBody = await response.Content.ReadAsStringAsync(); } catch (Exception) { return "ΠŸΡ€ΠΎΠ±Π»Π΅ΠΌΠ° с доступом ΠΊ " + Settings.TmURL; } Match match = new Regex("view\\/(.*?)\"", RegexOptions.IgnoreCase).Match(responseBody); if (match.Success) { Settings.TmLetterID = match.Groups[1].Value.Trim(); return "ΠŸΠΎΠ»ΡƒΡ‡Π΅Π½ΠΈΠ΅ ΠΊΠ»ΡŽΡ‡Π° Π½Π° Π²Ρ€Π΅ΠΌΠ΅Π½Π½Ρ‹ΠΉ ΠΏΡ€Π΅ΠΌΠΈΡƒΠΌ..."; } } return "Ошибка ΠΏΡ€ΠΈ ΠΏΠΎΠ»ΡƒΡ‡Π΅Π½ΠΈΠΈ письма с Π°ΠΊΡ‚ΠΈΠ²Π°Ρ†ΠΈΠ΅ΠΉ"; } public static async Task<string> GoPlaylist() { try { List<string> channelsInfo = new List<string>(); channelsInfo.Add($"#Name:Digitally Imported ({Settings.TmAddress}:{Settings.DiPass})"); channelsInfo.Add("#Cursor:-1"); JObject playlistJS = JObject.Parse(Settings.DiPlaylistJS); JToken[] channels = playlistJS["channels"].ToArray(); channelsInfo.Add($"#Summary:{channels.Count().ToString()} / 00:00:00:00 / 0 B"); channelsInfo.Add("#Flags:2047"); channelsInfo.Add("#Group:Radio|1"); int count = 0; return await Task.Run(() => { foreach (var data in channels) { count++; channelsInfo.Add($"#Track:{count}|http://prem2.di.fm:80/{data["key"].ToString()}_hi?{Settings.DiListenKey}||||{data["name"].ToString()}|0|0|||0|0|0"); } File.WriteAllLines($@"{Directory.GetCurrentDirectory()}\Digitally Imported.aimppl", channelsInfo); return "ΠŸΠ»Π΅ΠΉΠ»ΠΈΡΡ‚ ΡƒΡΠΏΠ΅ΡˆΠ½ΠΎ сгСнСрирован!"; }); } catch (Exception) { return "Ошибка ΠΏΡ€ΠΈ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠ΅ плСйлиста"; } } 
  • 3
    You must put the code you want to ask about in the question itself. The githaba code may change (and most likely will change), so in its current form the question will become useless for readers in just a few days. In addition, it makes sense for you to extract from your code only the part that is relevant to the question, because otherwise you will have to answer it (and they are lazy, because it is not their code). - VladD
  • Thanks, corrected. I did not immediately select a part of the code, because in principle there all the code is related to the question (in my opinion). - Disciple
  • And what does the SetHeader method do? - VladD
  • "SetHeader" adds headers to the request. Since I need to make several requests with the same headers and in order not to repeat the code, I decided to put it into the method. - Disciple
  • It's not entirely clear. Do you have one httpClient that is configured differently before each request? And what will happen if while waiting for the sending of one request another one will be sent? - VladD

1 answer 1

it is important to understand that Task constructs may be different. For example, Task.Factory.StartNew uses asynchronous state machines, and Task.Run constructs a separate thread on the CPU. This is very well described in the Microsoft .Net documentation .

 await Task.Run(() => { Thread.Sleep(3000); }); 

Here, the wait is not very well implemented, because Obviously, creating a new thread just to postpone the execution of the method is stupid, because It is very expensive. Use await Task.Delay(ms) . This is the way in which you receive data over the network. If you look at another example , then there may be several questions. The very first one: why do you have half the method in task, and half not? Wrap everything up in a task and remove async / await

 try { return Task.Run(() => DoSomething()); } catch {} 
  • Oh, there it is like ... Live and learn. Thank. - Disciple
  • Task.Factory.StartNew and Task.Run are the same with t. mechanism of work. - andreycha
  • as a whole - yes, but in the second case the task is placed in the pool of windows threads and executed in a separate thread - Arthur
  • @Arthur, what do you think happens in the first case, when Task.Factory.StartNew ? - sp7
  • one
    @Arthur no, they work the same way. The only differences are that Task.Run automatically deploys tasks, and the Task.Factory.StartNew interface allows Task.Factory.StartNew to control more things. Related article . Well, you can take a look at the source code: once and twice . - andreycha