How can i run Class Code in extra Thread? [duplicate] - c#

This question already has answers here:
WebBrowser Control in a new thread
(4 answers)
Closed 2 years ago.
i wanna get the content of 100 links as fast as possible. My first thought was to create one thread, that creates 100 Webbrowser objects, let them navigate and collect all html strings in a list. But when i try to run my code i get the error "actual thread is no singlethread-apartment".
I have the following Code:
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace WindowsFormsApp1
{
class ClassDriver
{
[STAThread]
public void StartDriver()
{
ClassTest t = new ClassTest();
Thread thread = new Thread(new ThreadStart(t.Collect));
thread.Start();
}
}
class ClassTest
{
private static List<WebBrowser> browsers;
private static List<string> htmls;
private static Stopwatch sw = new Stopwatch();
public void Collect()
{
string[] link = { "", "" };
sw.Start();
htmls = new List<string>();
browsers = new List<WebBrowser>();
for (int a = 0; a < 100; a++)
{
browsers.Add(new WebBrowser());
browsers.Last().DocumentCompleted += ClassGetRanking_DocumentCompleted;
browsers.Last().Navigate(link[0] + (a + 1) + link[1]);
}
}
private void ClassGetRanking_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
WebBrowser b = (sender as WebBrowser);
htmls.Add(b.DocumentText);
if (htmls.Count == browsers.Count)
{
sw.Stop();
}
}
}
}

The STAThread attribute you applied on StartDriver() method has no effect on the threads created by your own application.
You need to make them STA yourself by calling SetApartmentState() before calling Start()
Thread thread = new Thread(new ThreadStart(t.Collect));
thread.SetApartmentState(ApartmentState.STA);
thread.Start();
Ref:
https://learn.microsoft.com/en-us/dotnet/api/system.threading.thread.setapartmentstate

Related

OpenCvSharp VideoWriter writes an empty video

I am trying to read a vide file, resize the frames and write them to an output file:
using System;
using System.Drawing;
using System.Windows.Forms;
using OpenCvSharp;
using OpenCvSharp.Extensions;
namespace VideoProcessing
{
public class Player
{
private VideoCapture capture;
private VideoWriter writer;
private Mat matInternal;
public Bitmap bmInternal;
private bool bIsPlaying = false;
public Timer MyTimer = new Timer();
const string outname = "output.avi";
OpenCvSharp.Size dsize = new OpenCvSharp.Size(640, 480);
public void InitPlayer(string videoName)
{
capture = new VideoCapture(videoName);
writer = new VideoWriter(outname, FourCC.MJPG, capture.Fps, dsize);
matInternal = Mat.Zeros(dsize, MatType.CV_8UC3);
bmInternal = matInternal.ToBitmap();
var delay = 1000 / (int)capture.Fps;
MyTimer.Interval = delay;
MyTimer.Tick += new EventHandler(mk_onTick());
MyTimer.Start();
}
private Action<object, EventArgs>
mk_onTick()
{
return (object sender, EventArgs e) =>
{
capture.Read(matInternal);
if (matInternal.Empty())
{
Console.WriteLine("Empty frame!");
}
else
{
matInternal.Resize(dsize);
bmInternal = matInternal.ToBitmap();
writer.Write(matInternal);
}
};
}
public void Dispose()
{
capture.Dispose();
writer.Dispose();
}
}
}
This is executed in my main function as follows:
using System;
using System.Drawing;
using OpenCvSharp;
using OpenCvSharp.Extensions;
namespace VideoProcessing
{
internal class Program
{
private static void Main(string[] args)
{
var videoName = "input.mp4";
var pl = new Player();
pl.InitPlayer(videoName);
// Some other code that executes in the meantime
pl.Dispose();
}
}
}
The writer can get disposed before the video finishes, which is fine because this will later be adapted for live camera video streams. However, the VideoWriter here produces an apparently empty, 0 second long video file. The codec setting does not produce any errors, and the video is only at 24 FPS so it should not be running into any speed issues. What could be causing this?
I think you have to delay your main thread.
By adding Thread.Sleep(2000) for instance.
I try your code with camera and it works well.

C# Multithreading for three threads working in parallel and sending data to each other and working in order

I have a C# windows form program that uses three threads.
*The first thread is responsible for reading files from input folder and reading all text from each file then send data as string to the second thread using a Queue.
*The second thread is responsible on parsing the string got from the first thread, if the string was a number then send this number to the third thread also using a Queue.
*The third thread is responsible on creating file for the number got from thread 2.
Also I should have a Timer that runs thread 1 every 4 seconds for example until pressing stop.( should thread 2 and thread 3 when thread 1 runs after 4 seconds ?)
Note That the three threads should be running in parallel and should be in the correct order Thread 1 then Thread 2 then Thread 3 and should be getting and sending data for each other.
Below is an image for what i described below and some of the code that I used in my program.
Please I want your help I'm stuck in this ....
Code is :
form1.cs Class
using System;
using System.Collections.Concurrent;
using System.Threading;
using System.Collections.Generic;
using System.Collections.Concurrent;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace Mltithreading
{
public partial class Form1 : Form
{
public ConcurrentQueue<string> _queue = new ConcurrentQueue<string>();
public Queue<string> Queue1result = new Queue<string>();
public Queue<string> TestQueue = new Queue<string>();
public Queue<string> Queue2result = new Queue<string>();
public Form1()
{
InitializeComponent();
}
/* private Timer timer1;
public void InitTimer()
{
timer1 = new Timer();
timer1.Tick += new EventHandler(timer1_Tick);
timer1.Interval = 2000; // in miliseconds
timer1.Start();
} */
private void timer1_Tick(object sender, EventArgs e)
{
isonline();
}
public void isonline()
{
//
// The user selected a folder and pressed the OK button.
// We print the number of files found.
//
string[] files = Directory.GetFiles(folderBrowserDialog1.SelectedPath);
MessageBox.Show(files[0]);
var a = files[1];
var dir = new DirectoryInfo(folderBrowserDialog1.SelectedPath);
FileInfo[] f = dir.GetFiles();
foreach (System.IO.FileInfo fi in f)
{
Console.WriteLine("{0}: {1}: {2}", fi.Name, fi.LastAccessTime, fi.Length);
}
MessageBox.Show("Files found: " + files.Length.ToString(), "Message");
}
private void button1_Click(object sender, EventArgs e)
{
DialogResult result = folderBrowserDialog1.ShowDialog();
if (result == DialogResult.OK)
{
//
// The user selected a folder and pressed the OK button.
// We print the number of files found.
//
textBox1.Text = folderBrowserDialog1.SelectedPath;
/* try
{
string[] files = Directory.GetFiles(folderBrowserDialog1.SelectedPath);
var dir = new DirectoryInfo(folderBrowserDialog1.SelectedPath);
var output = folderBrowserDialog2.SelectedPath;
FileInfo[] f = dir.GetFiles();
Queue<FileInfo> Q = new Queue<FileInfo>(f);
while (Q.Count > 0)
{
FileInfo current = Q.Dequeue();
Console.WriteLine(current);
// Process 'current'
}
foreach (System.IO.FileInfo fi in f)
{
Console.WriteLine("{0}: {1}: {2}", fi.Name, fi.LastAccessTime, fi.Length);
}
MessageBox.Show("Files found: " + files.Length.ToString(), "Message");
}
catch (Exception excep)
{
Console.WriteLine("An error occurred: '{0}'", excep);
} */
}
}
private void Form1_Load(object sender, EventArgs e)
{
}
private void button2_Click(object sender, EventArgs e)
{
DialogResult result = folderBrowserDialog2.ShowDialog();
if (result == DialogResult.OK)
{
//
// The user selected a folder and pressed the OK button.
// We print the number of files found.
//
textBox2.Text = folderBrowserDialog2.SelectedPath;
}
}
private void button3_Click(object sender, EventArgs e)
{
string input = folderBrowserDialog1.SelectedPath;
string output = folderBrowserDialog2.SelectedPath;
var result = Thread1Start(input, output);
Console.WriteLine("Is thread Still Running :{0}", result);
//var firstThread = new Thread1();
var secondThread = new Thread2();
var thirdThread = new Thread3();
//Thread thread = new Thread(() => th.Readfiles(folderBrowserDialog1.SelectedPath, folderBrowserDialog2.SelectedPath));
//Thread thread1 = new Thread(delegate() { Queue1result = firstThread.Readfiles(folderBrowserDialog1.SelectedPath, folderBrowserDialog2.SelectedPath); });
//Thread thread3 = new Thread(() =>second.test(valueQueue));
Thread thread2 = new Thread(delegate() { Queue2result = secondThread.test(TestQueue); });
Thread thread3 = new Thread(() => thirdThread.CreateFiles(Queue2result,output));
//Thread thread5 = new Thread(second.run);
//thread1.Start();
// thread1.Join();
thread2.Start();
//thread2.Join();
thread3.Start();
//thread1.Start();
//thread1.Join();
//thread2.Start();
//thread1.Join(TimeSpan.Zero);
//Console.WriteLine(thread1.Join(TimeSpan.Zero));
// new System.Threading.Timer (ThreadTimer, "Thread 1 Started working...", 5000, 1000);
}
private void button4_Click(object sender, EventArgs e)
{
}
/* public void ThreadTimer (object data)
{
string input = folderBrowserDialog1.SelectedPath;
string output = folderBrowserDialog2.SelectedPath;
var result = Thread1Start(input, output);
Console.WriteLine("Is thread Still Running :{0}",result);
}
*/
public bool Thread1Start(string input, string output)
{
var firstThread = new Thread1();
Thread thread1 = new Thread(delegate() { Queue1result = firstThread.Readfiles(input, output); });
TestQueue = Queue1result;
thread1.Start();
Console.WriteLine("thread 1 start");
var state = thread1.Join(TimeSpan.Zero);
var secondThread = new Thread2();
var thirdThread = new Thread3();
//Thread thread = new Thread(() => th.Readfiles(folderBrowserDialog1.SelectedPath, folderBrowserDialog2.SelectedPath));
//Thread thread1 = new Thread(delegate() { Queue1result = firstThread.Readfiles(folderBrowserDialog1.SelectedPath, folderBrowserDialog2.SelectedPath); });
//Thread thread3 = new Thread(() =>second.test(valueQueue));
Thread thread2 = new Thread(delegate() { Queue2result = secondThread.test(Queue1result); });
Thread thread3 = new Thread(() => thirdThread.CreateFiles(Queue2result, output));
//Thread thread5 = new Thread(second.run);
//thread1.Start();
// thread1.Join();
thread2.Start();
//thread2.Join();
thread3.Start();
return state;
}
}
}
Thread1.cs class
here using System;
using System.IO;
using System.Text;
using System.Threading;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace Mltithreading
{
class Thread1
{
public void run()
{
while (true)
{
int iterations = 10;
try
{
for (int i = 0; i < iterations; i++)
{
Console.WriteLine("From Thread 1");
Thread.Sleep(2000);
}
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
}
}
public Queue<string> Readfiles(string inputDirectoryPath, string outputDirectoryPath)
{ Queue<string> thread1Queue = new Queue<string>();
try
{
var dir = new DirectoryInfo(inputDirectoryPath);
FileInfo[] f = dir.GetFiles();
foreach (System.IO.FileInfo fi in f)
{
var filePath = fi.DirectoryName + "\\" + fi.Name;
//File.Copy(filePath, outputDirectoryPath + "\\" + fi.Name);
// Open the file to read from.
string readText = File.ReadAllText(filePath);
thread1Queue.Enqueue(readText);
Console.WriteLine(readText);
Console.WriteLine("thread 1 call read files method ");
//Console.WriteLine("{0}: {1}: {2}", fi.Name, fi.LastAccessTime, fi.Length);
}
}
catch (Exception excep)
{
Console.WriteLine("An error occurred: '{0}'", excep);
}
return thread1Queue;
}
}
}
Thread2.cs class
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace Mltithreading
{
class Thread2
{
public void run()
{
while (true)
{
int iterations = 10;
try
{
for (int i = 0; i < iterations; i++)
{
Console.WriteLine("From Thread 2");
Thread.Sleep(2000);
}
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
}
}
public Queue<string> test(Queue<string> list)
{
Queue<string> thread2Queue = new Queue<string>();
while (list.Count > 0)
{
try
{
var a = list.Dequeue();
Console.WriteLine(a);
int j;
if (Int32.TryParse(a, out j))
{
Console.WriteLine("parsed the string {0} to integer and sent to thread 3", j);
thread2Queue.Enqueue(a);
}
else
Console.WriteLine("String could not be parsed to integer.");
Console.WriteLine("thread 2 parsing string from thread 1");
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
}
return thread2Queue;
}
}
}
Thread3.cs Class
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace Mltithreading
{
class Thread3
{
public void run()
{
while (true)
{
int iterations = 10;
try
{
for (int i = 0; i < iterations; i++)
{
Console.WriteLine("From Thread 3");
Thread.Sleep(2000);
}
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
}
}
public void CreateFiles(Queue<string> list, string outputDirectoryPath)
{
while (list.Count > 0)
{
string format = "MM-dd-yyyy--HH-mm-ss";
DateTime date = DateTime.Now;
string filename = date.ToString(format);
string file = outputDirectoryPath + "\\" + filename + ".txt";
var a = list.Dequeue();
FileInfo fi = new FileInfo(file);
if (!fi.Exists)
{
fi.Create().Dispose();
System.IO.File.WriteAllText(file,a);
Console.WriteLine("creating new text file {{0}}",file);
}
else
{
Console.WriteLine("file already exists");
}
Console.WriteLine(a);
Console.WriteLine("Thread 3 creating File with date name");
Console.WriteLine(date.ToString(format));
}
}
}
}
Thank you very much for your help .
I won´t comment on all, there´s too much stuff to talk about, but let´s have a look at your first thread.
Thread thread1 = new Thread(delegate() { Queue1result = firstThread.Readfiles(input, output); });
This line will create a thread that will replace the existing instance in your field Queue1Result (have a look at naming conventions, please!) once after reading some files (if existing). If executed again, The existing queue goes out of scope and will be replaced with a new one, probably not what you want to do.
You need to create those queue instances just once (type to use is ConcurrentQueue), those should then be used as a parameter running the thread procedure. So, redeclare the queues to readonly ConcurrentQueue to create the instances for your fields(give them a good "speaking" name, btw).
public readonly ConcurrentQueue<string> _textFromFilesQueue = new ConcurrentQueue<string>();
Once started, you want to regularly look after files again, so your code has to contain a loop.
This loop to be executed should be terminable from outside / other threads using a CancellationToken. Lets add a CancellationTokenSource to Form 1:
public CancellationTokenSource CancellationTokenSource { get; set; }
Your execution code for the first thread could / should look like this:
public void Readfiles(string inputDirectoryPath, string outputDirectoryPath, ConcurrentQueue<string> queue, CancellationToken cancellationToken)
{
while (!cancellationToken.IsCancellationRequested)
{
try
{
var dir = new DirectoryInfo(inputDirectoryPath);
FileInfo[] f = dir.GetFiles();
foreach (System.IO.FileInfo fi in f)
{
var filePath = Path.Combine(fi.DirectoryName, fi.Name);
//File.Copy(filePath, outputDirectoryPath + "\\" + fi.Name);
// Open the file to read from.
string textFromFile = File.ReadAllText(filePath);
queue.Enqueue(textFromFile);
Console.WriteLine(textFromFile);
Console.WriteLine("thread 1 call read files method ");
//Console.WriteLine("{0}: {1}: {2}", fi.Name, fi.LastAccessTime, fi.Length);
}
Thread.Sleep(TimeSpan.FromSeconds(5));
}
catch (Exception excep)
{
Console.WriteLine("An error occurred: '{0}'", excep);
Throw excep;
}
}
}
Do not build up a path by concatenating strings, use Path.Combine instead. Also, exceptions that happened should just be rethrown to ensure correct handling from other threads / tasks.
I would recommend using the TPL mechanisms instead of threads, it grants the system more flexibility in handling the tasks to be executed in a parallel manner. Have a look here : https://msdn.microsoft.com/de-de/library/dd460717(v=vs.110).aspx
So, creating and executing this task:
CancellationTokenSource = new CancellationTokenSource();
Task task = new Task(() => Readfiles(input, output, _textFromFilesQueue, CancellationTokenSource.Token));
task.Start();
Stopping the task:
CancellationTokenSource.Cancel();
Be sure not to overwrite the TokenSource without calling Cancel(), else you are losing the ability to stop the tasks that have already started...
EDIT: If you really need to ignore TPL, here is the example to execute the reading method with a thread:
Thread thread = new Thread(new ThreadStart(() => Readfiles(input, output, _textFromFilesQueue, CancellationTokenSource.Token)));
thread.Resume();
Use very simple and clear code:
var inputTexts = new BlockingCollection<string>();
var inputNumbers = new BlockingCollection<string>();
var readFiles = Task.Run(() =>
{
try
{
foreach (var file in Directory.EnumerateFiles("path", "searchPattern"))
{
string text = File.ReadAllText(file);
inputTexts.Add(text);
}
}
finally { inputTexts.CompleteAdding(); }
});
var processNumbers = Task.Run(() =>
{
try
{
foreach (var text in inputTexts.GetConsumingEnumerable())
{
int result;
if (int.TryParse(text, out result))
inputNumbers.Add(text);
}
}
finally { inputNumbers.CompleteAdding(); }
});
var createFiles = Task.Run(() =>
{
foreach (var number in inputNumbers.GetConsumingEnumerable())
{
string path = ""; // set fileName
File.WriteAllText(path, number);
}
});
Task.WaitAll(readFiles, processNumbers, createFiles);
It guarantees the execution in the correct order.
You can easily add cancellation using CancellationTokenSource.
Ok. Here is a working application that uses threads and timer.
It is assumed that execution all threads is faster than the timer interval.
New threads starts with each timer tick. The old threads will continue to work if they have not yet ended.
using System;
using System.Collections.Concurrent;
using System.IO;
using System.Threading;
using System.Windows.Forms;
namespace WindowsFormsApplication2
{
public partial class Form1 : Form
{
Button stopButton;
System.Windows.Forms.Timer timer;
public Form1()
{
//InitializeComponent();
stopButton = new Button { Parent = this, Text = "Stop" };
stopButton.Click += StopButton_Click;
timer = new System.Windows.Forms.Timer();
timer.Interval = 1000;
timer.Tick += Timer_Tick;
timer.Start();
Text = "Start";
}
private void StopButton_Click(object sender, EventArgs e)
{
timer.Stop();
Text = "Stop";
}
private void Timer_Tick(object sender, EventArgs e)
{
var inputTexts = new BlockingCollection<string>();
var inputNumbers = new BlockingCollection<string>();
var readFiles = new Thread(() =>
{
try
{
foreach (var file in Directory.EnumerateFiles("./Folder", "*.txt"))
{
string text = File.ReadAllText(file);
inputTexts.Add(text);
}
}
finally { inputTexts.CompleteAdding(); }
});
var processNumbers = new Thread(() =>
{
try
{
foreach (var text in inputTexts.GetConsumingEnumerable())
{
int result;
if (int.TryParse(text, out result))
inputNumbers.Add(text);
}
}
finally { inputNumbers.CompleteAdding(); }
});
var createFiles = new Thread(() =>
{
int counter = 0;
foreach (var number in inputNumbers.GetConsumingEnumerable())
{
File.WriteAllText("./Folder2/" + counter + ".txt", number);
counter++;
}
});
readFiles.Start();
processNumbers.Start();
createFiles.Start();
readFiles.Join();
processNumbers.Join();
createFiles.Join();
}
}
}

Download multiple files in parallel using c#

I want to download files in parallel using C#. For this, I have written this code which is working perfectly but the problem is that UI is freezing.
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Windows.Threading;
namespace FileDownloader
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
private static int count = 1;
private static string f= "lecture";
private string URL = "www.someexample.com";
public MainWindow()
{
InitializeComponent();
}
public static string GetDirectoryListingRegexForUrl(string url)
{
if (url.Equals(URL))
{
return "(?<name>.*)";
}
throw new NotSupportedException();
}
public void DownloadP(string[] urls)
{
Parallel.ForEach(urls.ToList(), new ParallelOptions { MaxDegreeOfParallelism = 10 }, DownloadFile);
}
private void DownloadFile(string url)
{
using(WebClient client=new WebClient())
{
if (url.EndsWith(".pdf"))
{
int nextIndex = Interlocked.Increment(ref count);
client.DownloadFile(url, f + nextIndex + ".pdf");
this.Dispatcher.Invoke(() => {
listbox.Items.Add(url);
});
}
}
}
private void Button_Click(object sender, RoutedEventArgs e)
{
DownloadP(listofFiles);
}
}
}
You can use async/await with conjunction with new WebClient method DownloadFileTaskAsync.
private async Task DownloadFile(string url)
{
if (!url.EndsWith(".pdf"))
{
return;
}
using (var client = new WebClient())
{
int nextIndex = Interlocked.Increment(ref count);
await client.DownloadFileTaskAsync(url, "lecture" + nextIndex + ".pdf");
listBox.Items.Add(url);
}
}
private async void Button_OnClick(object sender, RoutedEventArgs e)
{
button.IsEnabled = false;
await DownloadFiles(urlList);
button.IsEnabled = true;
}
private async Task DownloadFiles(IEnumerable<string> urlList)
{
foreach (var url in urlList)
{
await DownloadFile(url);
}
}
Relace your DownloadP function with this :
public async Task DownloadP(string[] urls)
{
await Task.Factory.StartNew(() => Parallel.ForEach(urls.ToList(), new ParallelOptions { MaxDegreeOfParallelism = 10 }, DownloadFile));
}
instead of using client.DownloadFile use client.DownloadFileAsync like this
var webClient=new WebClient();
webClient.DownloadFileCompleted += webClient_DownloadFileCompleted;
webClient.DownloadFileAsync("Your url","file_name");
the event
private void webClient_DownloadFileCompleted(object sender, AsyncCompletedEventArgs e)
{
MessageBox.Show("Download Completed.");
}
I know this Question is old, but WebClient is outdated and dedicated.
First of all, WPF uses MVVM pattern that you should try to follow, but except that you can use the HttpClient in using System.Net.Http;.
To download multiple files in a parallel you can create a parallel foreach that handles all the downloads that the HttpClient have to perform. You did tis right but the foreach will block the thread so start it in a new one Task.Run(()=>{// Your Code});
In the case you don’t want do write something like that yourself, you could use the Shard Download Library on NuGet. This NuGet Package is also on GitHub if you want to see how it does its job. It helped me often if I want do download a lot of files, because is does not block the UI thread and is easy to use. To use it you have to write something like this:
void Download()
{
string[] links = new string[]{
"https://google.com",
"https://speed.hetzner.de/100MB.bin",
"https://file-examples.com/storage/fe88dacf086398d1c98749c/2017/04/file_example_MP4_1920_18MG.mp4" };
foreach (var link in links)
{
_ = new LoadRequest(link);
}
Console.ReadLine();
}
But you can also set the MaxDegreeOfParalism and you can change it while it is downloading. You can set the Path for the output file and name it. The problem that the HttpClient has with download finished and progress report is also solved with this. The bad thing is that the documentation of this library is not very good. Here an example with few options as an example.
async Task DownloadAsync()
{
string[] links = new string[]{
"https://google.com",
"https://speed.hetzner.de/100MB.bin",
"https://file-examples.com/storage/fe88dacf086398d1c98749c/2017/04/file_example_MP4_1920_18MG.mp4" };
RequestHandler requestHandler = new()
{
MaxDegreeOfParallelism = 10
};
LoadRequestOptions option = new()
{
Progress = new Progress<float>(value => Console.WriteLine(value.ToString("0.0%"))),
DestinationPath = "C:\\Users\\[UserName]\\Desktop\\",
RequestCompleated = path => Console.WriteLine("Finished: " + path?.ToString()),
RequestHandler = requestHandler
};
LoadRequest last = null;
foreach (string link in links)
{
last = new LoadRequest(link, option);
}
await last.Task;
}
I hope that can help people that have the same problem and don’t want to use the dedicated WebClient.

How come I get no output from this piece of code?

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Timers;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
Timer time = new Timer();
time.Elapsed += new ElapsedEventHandler(action);
time.Interval = 5000;
time.Enabled = true;
time.Start();
}
static void action(Object sender, ElapsedEventArgs args)
{
Console.WriteLine("haha\n");
}
}
}
This piece of code doesnt have any output. Could anyone tell me what the problem is? Thank you very much. I followed exact code on MSDN.. http://msdn.microsoft.com/en-us/library/system.timers.timer(v=vs.71).aspx
Timer goes out of scope immediately and thus is never called. The program exits before it has a chance to fire the action.
You can make your main method sleep by adding this after time.start():
TimeSpan interval = new TimeSpan(0, 0, 2);
Thread.Sleep(interval);
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Timers;
class Program
{
static void Main(string[] args)
{
while(true)
{
Timer time = new Timer();
time.Elapsed += new ElapsedEventHandler(action);
time.Interval = 100;
time.Enabled = true;
time.Start();
string line = Console.ReadLine(); // Get string from user
if (line == "exit") // Check for exit condition
{
break;
}
}
Console.WriteLine("End of Program\n");
}
static void action(Object sender, ElapsedEventArgs args)
{
Console.WriteLine("haha\n");
}
}

Function works when called synchronously, but does not work when called asynchronously

It is my first post on StackOverflow forum so please to be lenient. I have a problem with function which works called synchronously, but doesnot works called asynchronously.
Below You will find function called synchronously:
private void issueInvoices(List<int> lista)
{
foreach (int knh_id in lista)
{
Invoice fs = new Invoice();
fs.FKS_AKCYZA = false;
fs.FKS_CZY_KLON = false;
fs.FKS_DATE = Convert.ToDateTime(MTBDataZapisuDoFK.Text);
fs.NUMBER = knh_id);
}
}
As You can see i passed list to function named issueInvoices list of invoice numbers and in loop i create some invoices.
This function works properly but if i try to call it asynchronously (to display progress bar) my function can not assign to fs.FKS_DATE object dateTime. It looks like static function “Convert.ToDateTime” doesnot work properly. But please take a look on below code where function issueInvoices is called asynchronously…
public delegate void BinaryDelegate(List<int> knh_id);
BinaryDelegate b = new BinaryDelegate(issueInvoices);
IAsyncResult theAsRes = b.BeginInvoke(lista, new AsyncCallback(AddComplete), "Thx U!");
FrmProgressBar fpb=new FrmProgressBar(“Please wait…”);
fpb.Show();
/* below i check how many operation i have to do, if all operations are done, then I close fpb window, program is updating progres bar and in thread make operation issueInvoices*/
while (ilosc_zrobionych != liczbaKontrahentow)
{
fpb.PBStan.Value = (int)((100 * ilosc_zrobionych) / liczbaKontrahentow);
}
fpb.Close();
I put some breakpoints and it looks like program stoping in line, it can conver to datetime, but when i do this synchronously, it works without any errors.
fs.FKS_DATE = Convert.ToDateTime(MTBDataZapisuDoFK.Text);
What could couse this problem and how to resolve it?
Many thanks in advance for reply.
BELOW IS WHOLE CLASS CALLED ASYNCHRONOUSLY:
using System;
using System.Collections.Generic;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Npgsql;
using Castle.ActiveRecord;
using WFR.Model;
using System.Threading;
namespace Faktury_i_Rachunki_2.Forms
{
public partial class FrmEmisjaFakturPotwierdzonych : FrmBaseForm
{
private ArrayList listaSposobowZaplaty;
public List<int> lista;
private int liczbaWygenerowach;
private int liczbaKontrahentow;
private int ilosc_zrobionych;
private FrmProgressBar fpb;
public delegate void BinaryDelegate(List<int> knh_id);
public FrmEmisjaFakturPotwierdzonych()
{
InitializeComponent();
fpb = new FrmProgressBar("Please wait....");
}
private void BtOK_Click(object sender, EventArgs e)
{
BinaryDelegate b = new BinaryDelegate(WyemitujFakture);
lista.Add(12);
lista.Add(13);
lista.Add(17);
lista.Add(1);
liczbaKontrahentow = lista.Count;
if (TBRejestr.Text.Trim() != "")
{
if (liczbaKontrahentow > 0)
{
liczbaWygenerowach = 0;
ilosc_zrobionych = 0;
WyemitujFakture(lista);
IAsyncResult theAsRes = b.BeginInvoke(lista, new AsyncCallback(AddComplete), "THX");
fpb.Show();
while (ilosc_zrobionych != liczbaKontrahentow)
{
fpb.PBStan.Value = (int)((100 * ilosc_zrobionych) / liczbaKontrahentow);
}
fpb.Close();
}
try
{
MessageBox.Show("Wygenerowano " + liczbaWygenerowach.ToString() + " faktur");
}
catch
{
}
}
}
private void WyemitujFakture(List<int> lista)
{
foreach (int knh_id in lista)
{
try
{
if (luk.Count > 0)
{
FakturySprzedazy fs = new FakturySprzedazy();
fs.FKS_AKCYZA = false;
fs.FKS_CZY_KLON = false;
fs.FKS_DATA_DOW_KS = Convert.ToDateTime(MTBDataZapisuDoFK.Text);
fs.FKS_DATA_FAKTURY = Convert.ToDateTime(MTBDataFaktury.Text);
fs.FKS_DATA_SPRZEDAZY = Convert.ToDateTime(MTBDataSprzedazy.Text);
liczbaWygenerowach++;
}
}
catch (Exception ex)
{
MessageBox.Show("Nie można wyemitować faktury dla kontrahenta o id = " + knh_id.ToString() + " " + ex.Message);
}
ilosc_zrobionych++;
}
}
You are accessing a UI control from a background thread:
MTBDataZapisuDoFK.Text
That is not allowed.
Get this value before calling the method, store it in a variable and send the value as an argument to issueInvoices.
The problem is in getting the value of MTBDataZapisuDoFK.Text (which I assume to be a textbox). Getting or setting the text of a textbox means sending messages to its window. But you keep the UI-thread busy in the while loop and therefore it can not process any messages.
Put a call to Application.DoEvents() into the while loop to allow messages to be processed:
fpb.Show();
while (ilosc_zrobionych != liczbaKontrahentow)
{
Application.DoEvents();
fpb.PBStan.Value = (int)((100 * ilosc_zrobionych) / liczbaKontrahentow);
}
fpb.Close();
I assume that the only reason for calling the method asynchronously is to be able to update the UI during processing the WyemitujFakture-method. Using Application.DoEvents() you do not need asynchonous calls:
fpb = new FrmProgressBar("Please wait....");
fpb.Show();
Application.DoEvents();
WyemitujFakture(lista);
fpb.Close();
You should call Application.DoEvents() after you call fpb.Show() to allow the form to be displayed properly. Also you should instantiate the form in the method itself instead of the constructor, because you can not use the same instance again after calling fpb.Close() (it will be disposed).
Then you can update the progress bar in the WyemitujFakture-method:
private void WyemitujFakture(List<int> lista)
{
foreach (int knh_id in lista)
{
try
{
if (luk.Count > 0)
{
FakturySprzedazy fs = new FakturySprzedazy();
fs.FKS_AKCYZA = false;
fs.FKS_CZY_KLON = false;
fs.FKS_DATA_DOW_KS = Convert.ToDateTime(MTBDataZapisuDoFK.Text);
fs.FKS_DATA_FAKTURY = Convert.ToDateTime(MTBDataFaktury.Text);
fs.FKS_DATA_SPRZEDAZY = Convert.ToDateTime(MTBDataSprzedazy.Text);
liczbaWygenerowach++;
}
}
catch (Exception ex)
{
MessageBox.Show("Nie mozna wyemitowac faktury dla kontrahenta o id = " + knh_id.ToString() + " " + ex.Message);
}
ilosc_zrobionych++;
fpb.PBStan.Value = (int)((100 * ilosc_zrobionych) / liczbaKontrahentow);
Application.DoEvents();
}
}

Categories