make multiple calls to same async tasks with different data c# - c#
I have a list which contains some documents (for simplicity strings). Now the list is getting populated slowly. What I want to do is when the size of the list reaches 20 I want to call another function that will print these strings asynchronously without stopping the main method. After lot of searching I have managed to put together this code
public void DoStuff()
{
Class1 p = new Class1();
List<string> list = new List<string> { };
var TList = new List<Task>();
int i = 0;
while (i < 90)
{
list.Add(i.ToString());
if (list.Count == 20)
{
Console.WriteLine("List contents when calling: " + list[0]);
TList.Add(Task.Run(() => publishDoc(list)));
list.Clear();
}
i++;
}
if (list.Count != 0)
{
TList.Add(Task.Run(() => publishDoc(list)));
}
Task.WhenAll(TList).Wait();
Console.WriteLine("Done DoStuff");
}
public async Task publishDoc(List<string> docs)
{
Console.WriteLine(iter++ + " " + docs[0]);
await Task.Run(() => Thread.Sleep(1000));
foreach (var val in docs)
{
Console.Write(val + " ");
}
Console.WriteLine();
}
This is what I am getting as output
List contents when calling: 0
List contents when calling: 20
List contents when calling: 40
List contents when calling: 60
1 80
3 80
0 80
2 80
4 80
80 80 80 80 81 82 83 84 85 86 87 88 89
81 82 83 84 85 86 87 88 89
81 82 83 84 85 86 87 88 89
81 82 83 84 85 86 87 88 89
80 81 82 83 84 85 86 87 88 89
Done DoStuff
Done Main
I can't figure out why it is only printing the last passed data i.e. why the passed list is getting overwritten.
Now if I do this
public void DoStuff()
{
Program2 p = new Program2();
List<string> list = new List<string> { };
int i = 0;
while (i < 90)
{
list.Add(i.ToString());
if (list.Count == 20)
{
Console.WriteLine("List contents when calling: " + list[0]);
var tasks = publishDoc(list);
if (tasks.Result == "Done")
{
Console.WriteLine("Done " + list[0]);
}
list.Clear();
}
i++;
}
if (list.Count != 0)
{
var tasks = publishDoc(list);
if (tasks.Result == "Done")
{
Console.WriteLine("Done " + list[0]);
}
}
Console.WriteLine("Done DoStuff");
}
public async Task<string> publishDoc(List<string> docs)
{
Console.WriteLine(iter++ + " " + docs[0]);
foreach (var val in docs)
{
Console.Write(val + " ");
}
Console.WriteLine();
return await Task.Run(() => "Done");
}
I get this output
List contents when calling: 0
0 0
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
Done 0
List contents when calling: 20
1 20
20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
Done 20
List contents when calling: 40
2 40
40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59
Done 40
List contents when calling: 60
3 60
60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79
Done 60
4 80
80 81 82 83 84 85 86 87 88 89
Done 80
Done DoStuff
Done Main
This is giving the correct output but is doing it synchronously which I don't want. Please help and thanks in advance.
you have to do like this , as in loop it points to same instance of list every time that might causing issue , so I suggest you create copy of list before passing it to function publishDoc
while (i < 90)
{
list.Add(i.ToString());
if (list.Count == 20)
{
List<string> copy = list.ToList();
Console.WriteLine("List contents when calling: " + copy[0]);
TList.Add(Task.Run(() => publishDoc(copy)));
list.Clear();
}
i++;
}
Refer this answer also : Starting Tasks In foreach Loop Uses Value of Last Item
Related
WebClient is not following redirects in .Net Core 3.1
I try to download a file with a URL that returns a 307 redirect code. I tried using the WebClient.DownloadFile method, but it seems to not follow the redirects of the requested site. The stuff i found by searching for this issue either says it should work (Microsoft docs) or does not really answer my questions: WebClient Does not automatically redirect My first question here is why is it not following the redirect, even if the HttpWebRequest it uses has AllowAutoRedirect=true? My second question is how to best implement a function which downloads a file with automatic redirects. An example URL i'm using would be: https://api.spiget.org/v2/resources/10905/download But this URL is not allways redirecting, depending on some internal API states i guess.
Here's a simple example with HttpClient .NET Core 3.1 Console app (UPD: added progress reporting) class Program { private static readonly HttpClient client = new HttpClient(new HttpClientHandler() { AllowAutoRedirect = true }); static async Task Main(string[] args) { try { IProgress<int> progress = new Progress<int>(p => { Console.Write(p + " "); }); await DownloadAndSaveFileAsync("https://api.spiget.org/v2/resources/10905/download", progress); Console.WriteLine(); } catch (Exception ex) { Console.WriteLine(ex.Message); } Console.WriteLine("Done."); Console.ReadKey(); } private static async Task DownloadAndSaveFileAsync(string url, IProgress<int> progress) { using HttpResponseMessage response = await client.GetAsync(url, HttpCompletionOption.ResponseHeadersRead).ConfigureAwait(false); response.EnsureSuccessStatusCode(); // throw if not success string fileName = response.Content.Headers.ContentDisposition?.FileName ?? throw new Exception("Nothing to download"); fileName = fileName.Trim('\"'); // remove quotes long contentLength = response.Content.Headers.ContentLength ?? 0; Console.WriteLine("File: {0}", fileName); Console.WriteLine("Content-Length: {0} bytes", contentLength); using Stream responseStream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false); using FileStream fileStream = File.Create(fileName); int bufferSize = 65536; byte[] buffer = new byte[bufferSize]; int bytesRead; long position = 0; int storedPercentage = -1; while ((bytesRead = await responseStream.ReadAsync(buffer, 0, bufferSize)) > 0) { await fileStream.WriteAsync(buffer, 0, bufferSize); if (contentLength > 0) { position += bytesRead; int percentage = (int)(position * 100 / contentLength); if (percentage != storedPercentage) { progress?.Report(percentage); storedPercentage = percentage; } } } } } Console output File: [1.8 TO 1.16] Ultra Cosmetics [OPENSOURCE & FREE!!]#10905.jar Content-Length: 1692542 bytes 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 73 72 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 Done. File downloaded successfully. Compared byte-by-byte with downloaded in browser. Files are idential.
having formatting error in c#
static void Main(string[] args) { OpenFiles(); PrintReportHeadings(); while ((lineIn = fileIn.ReadLine()) != null) { ParseLineIn(); PrintDetailLine(); Computing(); sides++; } CloseFiles(); } static void PrintDetailLine() { Console.WriteLine("{0,2} {1}", sides, polyName); } static void Computing() { for (n = 1; n <= 9; n++) { p = (Math.Pow(n, 2) * (sides - 2) - n * (sides - 4)) / 2; Console.Write("{0}", p); } } Here is the code I'm working with. I have my report headings where they need to be and when reading in polygon names from file, they go into the right spot with the amount of sides. But when trying to compute the nth amount of dots in polygonal number, it pushes the amount of sides of polygon and name of polygon to the right side. not sure what I'm doing wrong. been staring at this for 4 hours now.
Is this what you are after? Output: 3 Triangular 1 3 6 10 15 21 28 36 45 4 Square 1 4 9 16 25 36 49 64 81 5 Pentagonal 1 5 12 22 35 51 70 92 117 6 Hexagonal 1 6 15 28 45 66 91 120 153 7 Heptagonal 1 7 18 34 55 81 112 148 189 8 Octagonal 1 8 21 40 65 96 133 176 225 9 Nonagonal 1 9 24 46 75 111 154 204 261 10 Decagonal 1 10 27 52 85 126 175 232 297 11 Hendecagonal 1 11 30 58 95 141 196 260 333 12 Dodecagonal 1 12 33 64 105 156 217 288 369 13 Tridecagonal 1 13 36 70 115 171 238 316 405 14 Tetradecagonal 1 14 39 76 125 186 259 344 441 15 Pentadecagonal 1 15 42 82 135 201 280 372 477 16 Hexadecagonal 1 16 45 88 145 216 301 400 513 17 Heptadecagonal 1 17 48 94 155 231 322 428 549 18 Octadecagonal 1 18 51 100 165 246 343 456 585 19 Nonadecagonal 1 19 54 106 175 261 364 484 621 20 Icosagonal 1 20 57 112 185 276 385 512 657 21 Icosihenagonal 1 21 60 118 195 291 406 540 693 22 Icosidigonal 1 22 63 124 205 306 427 568 729 23 Icositrigonal 1 23 66 130 215 321 448 596 765 24 Icositetragonal 1 24 69 136 225 336 469 624 801 Press any key to continue . . . Source Code: class Program { static int sides = 3; private static int maxPolyNameLength; static void Main(string[] args) { var input = "Triangular Square Pentagonal Hexagonal Heptagonal Octagonal Nonagonal Decagonal Hendecagonal Dodecagonal Tridecagonal Tetradecagonal Pentadecagonal Hexadecagonal Heptadecagonal Octadecagonal Nonadecagonal Icosagonal Icosihenagonal Icosidigonal Icositrigonal Icositetragonal" .Split(' '); maxPolyNameLength = input.Max(x => x.Length); foreach (var s in input) { PrintDetailLine(s); Computing(); Console.WriteLine(); sides++; } } static void PrintDetailLine(string polyName) { Console.Write($"{{0,2}} {{1,{maxPolyNameLength}}} ", sides, polyName); } static void Computing() { double p = 0; for (var n = 1; n <= 9; n++) { p = (Math.Pow(n, 2) * (sides - 2) - n * (sides - 4)) / 2; Console.Write("{0,3} ", p); } } }
How can i convert HEX to ASCII and only get the number from it?
I am receiving data from weighing scale(serial port) as HEX. I want to convert it to ASCII and only need the weight from it. Code: private void button1_Click(object sender, EventArgs e) { if (_serialPort != null && _serialPort.IsOpen) _serialPort.Close(); if (_serialPort != null) _serialPort.Dispose(); _serialPort.BaudRate = Convert.ToInt16(cbBaud.Text); _serialPort = new SerialPort(comboBox1.Text, BaudRate, Parity.None, 8, StopBits.One); _serialPort.DataReceived += SerialPortOnDataReceived; _serialPort.Open(); textBox1.Text = string.Format("Listening on {0}...", comboBox1.Text); } private delegate void Closure(); private void SerialPortOnDataReceived(object sender, SerialDataReceivedEventArgs serialDataReceivedEventArgs) { if (InvokeRequired) BeginInvoke(new Closure(() => { SerialPortOnDataReceived(sender, serialDataReceivedEventArgs); })); else { while (_serialPort.BytesToRead > 0) { textBox1.Text += string.Format("{0:X2} ", _serialPort.ReadByte()); } } This is my output: Listening on COM1...20 20 20 30 0D 28 02 71 70 30 20 20 20 20 38 30 20 20 20 20 20 30 0D 28 02 71 70 30 20 20 20 20 38 30 20 20 20 20 20 30 0D 28 02 71 70 30 20 20 20 20 38 30 20 20 20 20 20 30 0D 28 02 71 70 30 20 20 20 20 38 30 20 20 20 20 20 30 0D 28 02 71 70 30 20 20 20 20 38 30 20 20 20 20 20 30 0D 28 02 71 70 30 20 20 20 20 38 30 20 20 20 20 20 30 0D 28 02 71 70 30 20 20 20 20 38 30 20 20 20 .... preview This is ASCII code that i converted manually from a website: 0 ( q p 0 8 0 0 ( q p 0 8 0 0 ( q p 0 8 0 0 ( q p 0 8 0 0 ( q p 0 8 0 0 ( q p 0 8 0 0 ( q p 0 8 0
You have copied some expample but there are more suitable methods to read from serial port that would better suit your purpose. First you need to determine the data format of the weighting indicator from the manual. Then you can use this (instead of the while loop): string myData = _serialPort.ReadTo("\r"); where "\r" weight record delimiter (it could be also other strings like <CR><LF>, <STX> <ETX> etc.) If you want to read all available input data from the serial port buffer, you can use string myData = _serialPort.ReadExisting(); and split the string by specified char string[] weightRecords = myData.Split('\r'); Then you parse the weight numeric values from the obtained strings. So you do not need to convert data from bytes, you can read it directly as a string. If you need more inspiration, check this project. If you want to try it, you can rewrite the body of your DataReceived handler like this: if (InvokeRequired) BeginInvoke(new Closure(() => { SerialPortOnDataReceived(sender, serialDataReceivedEventArgs); })); else { //There may be multiple records available in the Serial Port buffer string myData = _serialPort.ReadExisting(); //Suppose that 0D character (equals to \r) marks the end of record, see manual of the indicator string[] weightRecords = myData.Split('\r'); foreach (var s in weightRecords) { //9,5 = Position and length of the numeric weight value, for exact values see your weight indicator manual textBox1.Text += string.Format("{0} kg \n", s.Substring(9,5)); } } To split your string by delimiters consisting of multiple chars, you can use something like this: string[] stringSeparators = new string[] { System.Text.Encoding.ASCII.GetString(new byte[] {0x0d, 0x28}) }; string[] weightRecords = myData.Split(stringSeparators, StringSplitOptions.None);
How to get full branch coverage of C#'s async/await using nunit and opencover
In c#, async and await are turned into a state machine at compile time. My problem is hitting each piece of the state machine. I've decompiled the code and ran my exact same unit test against it to find out which branch I'm missing. 49 void IAsyncStateMachine.MoveNext() 4 50 { 4 51 int result1 = 0; 52 try 4 53 { 4 54 bool flag = true; 55 TaskAwaiter<int> awaiter; 4 56 switch (this._state) 57 { 58 case -3: 0 59 goto label_6; 60 case 0: 1 61 awaiter = this._awaiter2; 1 62 this._awaiter2 = new TaskAwaiter<int>(); 1 63 this._state = -1; 1 64 break; 65 default: 3 66 awaiter = this._this._additionAsync.Add(this.value1, this.value2).GetAwaiter(); 2 67 if (!awaiter.IsCompleted) 1 68 { 1 69 this._state = 0; 1 70 this._awaiter2 = awaiter; 1 71 this._builder.AwaitUnsafeOnCompleted<TaskAwaiter<int>, CalculatorAsync.d__0>(ref awaiter, ref this); 1 72 flag = false; 1 73 return; 74 } 1 75 break; 76 } 2 77 int result2 = awaiter.GetResult(); 2 78 awaiter = new TaskAwaiter<int>(); 2 79 this._results1 = result2; 2 80 result1 = this._results1; 2 81 } 1 82 catch (Exception ex) 1 83 { 1 84 this._state = -2; 1 85 this._builder.SetException(ex); 1 86 return; 87 } 88 label_6: 2 89 this._state = -2; 2 90 this._builder.SetResult(result1); 4 91 } Above you can see that line 59 is hit 0 times in terms of coverage. According to this article http://www.codeproject.com/Articles/535635/Async-Await-and-the-Generated-StateMachine it's hit when the machine is requested to stop. I haven't been able cancel the async call in a manner that hits the case. This is a test I thought would hit it but isn't. [Test] [ExpectedException("System.InvalidOperationException")] public async void DecompiledCancellationTest() { var expectedResult = 4; var tcs = new TaskCompletionSource<int>(); tcs.SetResult(4); var additionHandler = new Mock<IAdditionHandler>(); additionHandler.Setup(x => x.Add(2, 2)).Returns(tcs.Task); tcs.SetCanceled(); var calculator = new CalculatorAsync(additionHandler.Object); var aTaskResponse = calculator.AddDecompiled(2, 2); var aResponse = await aTaskResponse; Assert.AreEqual(expectedResult, aResponse); } I've uploaded a sample to github Using Asp.Net 4.5, Nunit 2.6.4, OpenCover 4.5.3522, and ReportGenerator 2.1.4.0 How do I get that line covered?
Read string of numbers into a grid/matrix [closed]
Closed. This question needs details or clarity. It is not currently accepting answers. Want to improve this question? Add details and clarify the problem by editing this post. Closed 8 years ago. Improve this question Can anyone tell me how can I read this grid into arrays like a[i][j] ? I searched on google but I can't seem to find anything useful.Thank you very much for helping! static void Main(string[] args) { String grid = "08 02 22 97 38 15 00 40 00 75 04 05 07 78 52 12 50 77 91 08" + "49 49 99 40 17 81 18 57 60 87 17 40 98 43 69 48 04 56 62 00" + "81 49 31 73 55 79 14 29 93 71 40 67 53 88 30 03 49 13 36 65" + "52 70 95 23 04 60 11 42 69 24 68 56 01 32 56 71 37 02 36 91" + "22 31 16 71 51 67 63 89 41 92 36 54 22 40 40 28 66 33 13 80" + "24 47 32 60 99 03 45 02 44 75 33 53 78 36 84 20 35 17 12 50" + "32 98 81 28 64 23 67 10 26 38 40 67 59 54 70 66 18 38 64 70" + "67 26 20 68 02 62 12 20 95 63 94 39 63 08 40 91 66 49 94 21" + "24 55 58 05 66 73 99 26 97 17 78 78 96 83 14 88 34 89 63 72" + "21 36 23 09 75 00 76 44 20 45 35 14 00 61 33 97 34 31 33 95" + "78 17 53 28 22 75 31 67 15 94 03 80 04 62 16 14 09 53 56 92" + "16 39 05 42 96 35 31 47 55 58 88 24 00 17 54 24 36 29 85 57" + "86 56 00 48 35 71 89 07 05 44 44 37 44 60 21 58 51 54 17 58" + "19 80 81 68 05 94 47 69 28 73 92 13 86 52 17 77 04 89 55 40" + "04 52 08 83 97 35 99 16 07 97 57 32 16 26 26 79 33 27 98 66" + "88 36 68 87 57 62 20 72 03 46 33 67 46 55 12 32 63 93 53 69" + "04 42 16 73 38 25 39 11 24 94 72 18 08 46 29 32 40 62 76 36" + "20 69 36 41 72 30 23 88 34 62 99 69 82 67 59 85 74 04 36 16" + "20 73 35 29 78 31 90 01 74 31 49 71 48 86 81 16 23 57 05 54" + "01 70 54 71 83 51 54 69 16 92 33 48 61 43 52 01 89 19 67 48"; int[] a = new int[20]; for(int i=0;i<20;i++) for (int j = 1; j < 20; j++) { } }
As suggested in the comments you can simply separate your numbers and use split string. for example: private static void Main(string[] args) { String grid = "08,02,22,97,38,15,00,40,00,75,04,05,07,78,52,12,50,77,91,08," + "49,49,99,40,17,81,18,57,60,87,17,40,98,43,69,48,04,56,62,00," + "81,49,31,73,55,79,14,29,93,71,40,67,53,88,30,03,49,13,36,65," + "52,70,95,23,04,60,11,42,69,24,68,56,01,32,56,71,37,02,36,91," + "22,31,16,71,51,67,63,89,41,92,36,54,22,40,40,28,66,33,13,80," + "24,47,32,60,99,03,45,02,44,75,33,53,78,36,84,20,35,17,12,50," + "32,98,81,28,64,23,67,10,26,38,40,67,59,54,70,66,18,38,64,70," + "67,26,20,68,02,62,12,20,95,63,94,39,63,08,40,91,66,49,94,21," + "24,55,58,05,66,73,99,26,97,17,78,78,96,83,14,88,34,89,63,72," + "21,36,23,09,75,00,76,44,20,45,35,14,00,61,33,97,34,31,33,95," + "78,17,53,28,22,75,31,67,15,94,03,80,04,62,16,14,09,53,56,92," + "16,39,05,42,96,35,31,47,55,58,88,24,00,17,54,24,36,29,85,57," + "86,56,00,48,35,71,89,07,05,44,44,37,44,60,21,58,51,54,17,58," + "19,80,81,68,05,94,47,69,28,73,92,13,86,52,17,77,04,89,55,40," + "04,52,08,83,97,35,99,16,07,97,57,32,16,26,26,79,33,27,98,66," + "88,36,68,87,57,62,20,72,03,46,33,67,46,55,12,32,63,93,53,69," + "04,42,16,73,38,25,39,11,24,94,72,18,08,46,29,32,40,62,76,36," + "20,69,36,41,72,30,23,88,34,62,99,69,82,67,59,85,74,04,36,16," + "20,73,35,29,78,31,90,01,74,31,49,71,48,86,81,16,23,57,05,54," + "01,70,54,71,83,51,54,69,16,92,33,48,61,43,52,01,89,19,67,48"; var splitstring = grid.Split(','); var a = new int[20,20]; const int rowCount = 19; //counts 0 as 1 var rowIndex = 0; var colIndex = 0; foreach (var s in splitstring) { if (rowIndex > rowCount) { rowIndex = 0; colIndex++; } a[colIndex, rowIndex] = Int32.Parse(s); rowIndex++; } } Note the Int32.Parse(s) will throw an exception if the parse fails. You can instead use an Int32.TryParse and use the out value for your result. Depends on what you want to do.
Consider add a space to the end of each "line" such as the following: String grid = "08 02 .. 91 08 " + "01 70 .. 67 48 "; // ^-- add space here This will allow the string to be converted trivially into a 1D array of strings with string.Split. string grid = "08 02 .. 91 08"; // every number is space-separated now string[] gridArray = grid.Split(" "); // -> ["08", "02", .. "91", "08"] (Even without ensuring the extra spaces, a 1D array can be achieved using a Regular Expression split: var gridArray = Regex.Split(grid, "(?:\s|(?<=\d{2})(?=\d{2}))"), but I recommend "normalizing" the input string literals if possible.) And each index in the resulting 1D array can be accessed as so, where columns represents the number of columns of the super-imposed matrix, or the "width" of each row. int columns = 20; int gridIndex = j * columns + i; // where j is a *row* and i is a *column* // for a column-major matrix string numStr = gridArray[gridIndex]; // and value at the [column,row] Then it's just a matter of converting numStr to an integer and assigning it to the appropriate array index. If every number is separated by a space such that ever number NN is in form "NN " it also takes up 3 characters. In this case the intermediate Split can be skipped, using the same idea of indexing into the source as a 1D sequence. int gridNumOffset = (j * columns + i) * 3; string numStr = grid.Substring(gridNumOffset, 2); (Finding the substring offset even when there is no space at the end-of-line can be done using a little bit more math, which is a good exercise and the formula just becomes (j * columns + i) * 3 + f(i), where f(i) applies the appropriate offset.) Another more mundane approach, assuming that the original string cannot be modified to include an end-of-line space/character, is to read in each line as N characters, deal with it, and move on. The concepts from above can be applied: int rowWidth = (columns * 3) - 1; // -1 assuming no line-end space for(int j = 0; j < rows; j++) { // j is *rows*, for column-major matrix string rowStr = str.Substring(j * rowWidth, rowWidth); string[] row = rowStr.Split(" "); // 1D array just for this row for (int i = 0; i < columns; i++) { string numStr = row[i]; // Convert and put value into the correct matrix position } }