The requirement is to call a method after every 12 hours. The code below the method call should keep on running in different thread, how can we achieve this?
void ExecuteAfterTimeInterval()
{
//some code
}
public static void main(string[] args)
{
//call the below method after every 12 hours
ExecuteAfterTimeInterval();
// run the below code in separate thread
// some code here
//some code here
//some code here
}
Give this a try. Look for //SET BREAK POINT HERE and run.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;
namespace MyConsole
{
class Program
{
static void Main(string[] args)
{
Program console = new Program();
console.MyMethodAsync();
}
void ExecuteAfterTimeInterval()
{
//some code
}
public async Task MyMethodAsync()
{
Task<int> longRunningTask = LongRunningOperationAsync();
// run the below code in separate thread
//some code here
//some code here
for (int i = 0; i < 10000000000; i++)
{
Console.WriteLine(i); //SET BREAK POINT HERE
}
//some code here
//and now we call await on the task
int result = await longRunningTask;
}
public async Task<int> LongRunningOperationAsync() // assume we return an int from this long running operation
{
bool retry = true;
using (AutoResetEvent wait = new AutoResetEvent(false))
{
while (retry)
{
//Do Work here
//await Task.Delay(43200000); //12 hour delay
await Task.Delay(3000); //SET BREAK POINT HERE
}
}
return 1;
}
}
}
Related
I'm trying to create a file copy application. I have a BackgroudWorker doing the work and it works fine so far. How it works, I have a form, Source and Destination Folder fields and a Copy button. The Copy button triggers the Copy operation using the BackgroundWorker. The Progressbar gets updated etc. Now I need to implemet a queue type of operation. I need to add other Source and Destination Copy operation and add it to the queue. I tried using the following:
Queue<MethodInvoker> MyQueue = new Queue<MethodInvoker>();
MyQueue.Enqueue(new MethodInvoker(() =>CopyStuff(1)));
MyQueue.Enqueue(new MethodInvoker(() =>CopyStuff(2)));
MethodInvoker bb = MyQueue.Dequeue(); //(I Forgot this part)
bb();
bb = MyQueue.Dequeue();
bb();
The problem is, because it's a BackgroundWorker, it does not wait for the first operation to complete. Any suggestions on how to go about this?
After fixing my code it works, except for it running on the UI thread, locking controls.
Update 1:
This works, but runs on main thread, user can't use controls while it's running:
BlockingCollection<MethodInvoker> bCollection = new BlockingCollection<MethodInvoker>(boundedCapacity: 2);
Task producerThread = Task.Factory.StartNew(() =>
{
for (int i = 0; i < 2; ++i)
{
bCollection.Add(CopyStuff);
}
bCollection.CompleteAdding();
});
foreach (MethodInvoker item in bCollection.GetConsumingEnumerable())
{
BeginInvoke(item);
}
Update 2:
Works in a Console App, but not a Windows Forms Application.
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace AsyncCopy
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
}
public class AsyncCopy
{
private static Queue<Action> MyQueue = new Queue<Action>();
public async Task EnqueueAndCopy(Action[] actionList)
{
foreach (var action in actionList)
{
MyQueue.Enqueue(action);
}
while (MyQueue.TryDequeue(out var copyAction)) //Here's the problem on Windows Form Applivcation
{
//If the copyaction is itself async, await directly on the method here instead of running the action in a Task
await Task.Factory.StartNew(copyAction);
}
}
}
private void button1_Click(object sender, EventArgs e)
{
var asyncCopy = new AsyncCopy();
//In a typical usage, this will call be awaited
//In your case, make this call from a async method and call it from the UI thread
asyncCopy.EnqueueAndCopy(
new Action[] {
() => CopyStuff (1),
() => CopyStuff (2)
}
);
//Loop to confirm the processing is asynchronous
for (int i = 0; i <= 20; i++)
{
Console.WriteLine($"{i}");
Thread.Sleep(300);
}
}
//Copy process simulation
static void CopyStuff(int i)
{
Console.WriteLine($"Copying {i}");
Thread.Sleep(3000);
Console.WriteLine($"Copied {i}");
}
}
}
If you need to Queue the Copy process asynchronously as the other copies are processing, I would recommend a producer consumer pattern. Refer https://www.dotnetcurry.com/patterns-practices/1407/producer-consumer-pattern-dotnet-csharp
But a simple async await would work in your case as well
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using System.Threading;
namespace stackoverflow {
class Program {
static void Main (string[] args) {
var asyncCopy = new AsyncCopy ();
//In a typical usage, this will call be awaited
//In your case, make this call from a async method and call it from the UI thread
asyncCopy.EnqueueAndCopy (
new Action[] {
() => CopyStuff (1),
() => CopyStuff (2)
}
);
//Loop to confirm the processing is asynchronous
for(int i=0; i <= 20; i++)
{
Console.WriteLine($"{i}");
Thread.Sleep(300);
}
}
//Copy process simulation
static void CopyStuff (int i) {
Console.WriteLine ($"Copying {i}");
Thread.Sleep(3000);
Console.WriteLine ($"Copied {i}");
}
}
public class AsyncCopy {
private static Queue<Action> MyQueue = new Queue<Action> ();
public async Task EnqueueAndCopy (Action[] actionList) {
foreach (var action in actionList) {
MyQueue.Enqueue (action);
}
while (MyQueue.TryDequeue (out var copyAction)) {
//If the copyaction is itself async, await directly on the method here instead of running the action in a Task
await Task.Factory.StartNew (copyAction);
}
}
}
}
Update
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private async Task CopyAsync(IEnumerable<Action> actionList)
{
foreach (var action in actionList)
{
await Task.Factory.StartNew(action);
}
}
private async void button2_Click(object sender, EventArgs e)
{
await CopyAsync(
new Action[]
{
() => CopyStuff(1),
() => CopyStuff(2)
});
}
//Copy process simulation
static void CopyStuff(int i)
{
Thread.Sleep(3000);
MessageBox.Show(string.Format("File Copied {0}", i));
}
}
}
The question is that, what happens to a thread when the function has already been executed and the thread is started in that function. (please see an example below)
public int Intialise ()
{
int i = startServer();
Thread readall = new Thread(readAllMessage);
if (i == 1)
readall.Start();
else
MessageBox.Show("Connection Error");
return i;
}
I want 'readall' to continue (forever or till the application is closed) even if the function is executed. Is it possible? Because for me the thread stops immediately even when the true condition is met. Please shed some light.
OK, here is your code slightly modified to include the loop.
internal class Program
{
public static int Intialise()
{
int i = startServer();
Thread readall = new Thread(readAllMessage);
readall.IsBackground = true; // so that when the main thread finishes, the app closes
if (i == 1)
readall.Start();
else
Console.WriteLine("Error");
return i;
}
public static void readAllMessage()
{
while (true)
{
Console.WriteLine("reading...");
Thread.Sleep(500);
}
}
public static int startServer()
{
return 1;
}
private static void Main(string[] args)
{
var i = Intialise();
Console.WriteLine("Init finished, thread running");
Console.ReadLine();
}
}
when you run it, it will print:
Init finished, thread running
reading...
reading...
reading...
and when you press enter (see Console.ReadLine()) it will stop running.
If you change the IsBackground to TRUE it would not exit the process.
Here is an example of what you ask
using System;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace ForeverApp
{
class SomeObj
{
public void ExecuteForever()
{
while (true)
{
Thread.Sleep(1000);
Console.Write(".");
}
}
}
class Program
{
static void Main(string[] args)
{
SomeObj so = new SomeObj();
Thread thrd = new Thread(so.ExecuteForever);
thrd.Start();
Console.WriteLine("Exiting Main Function");
}
}
}
If I have a given method, for example:
protected Task CreateItemsAsync(object source)
{
return Task.Factory.StartNew(() =>
{
///////
code
///////
}
}
I have a bunch of code in the method but I cannot step into the method. Is there a way to proceed step by step in the code?
Try this code in a Console app:
using System;
using System.Threading.Tasks;
namespace Demo
{
public static class Program
{
[STAThread]
private static void Main()
{
var task = test();
Console.WriteLine(task.Result);
}
private static Task<int> test()
{
return Task<int>.Factory.StartNew(() =>
{
int x = 10; // <-- Set a breakpoint here.
int y = 5;
int z = x/y;
return z;
});
}
}
}
Set a breakpoint at the indicated line, and then debug the program.
The debugger will stop at the indicated line, and you will be able to single-step through the rest of the lines in the thread.
I'm creating a weather app that polls temperature from a service I've made:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;
namespace Weather
{
class Program
{
static BackgroundWorker bgw;
static void Main(string[] args)
{
bgw = new BackgroundWorker();
bgw.DoWork += bgw_DoWork;
bgw.RunWorkerAsync();
}
static async void bgw_DoWork(object sender, DoWorkEventArgs e)
{
Weather bot = new Weather();
if (bot.IsRunning)
{
await bot.Update();
}
}
}
public class Weather
{
public bool IsRunning { get; set; }
private DateTime lastUpdated;
public Weather()
{
IsRunning = true;
lastUpdated = DateTime.Now.AddDays(-1);
}
public async Task<bool> Update()
{
if (lastUpdated < DateTime.Now)
{
lastUpdated = DateTime.Now.AddSeconds(30);
// temperature
double value = await GetLatestValue("New York");
}
return true;
}
private async Task<double> GetLatestValue(string city)
{
string url = "http://www" + city;
var client = new WebClient();
string data = await client.DownloadStringTaskAsync(url);
return 4.3;
}
}
}
The problem here is that it does not seem to work? The GetLatesValue function is just jibberish, will just return 4.3 for testing purposes.
What happens is that on await GetLatestValue the console application just quits.
The problem is simpler than you might think: you are running a BackgroundWorker, which basically wraps a thread that has .IsBackground = true. Such threads will not keep a process alive - they will be shut down automatically when the process exits. The process will exit when all non-background threads are completed.
Your Main method starts the BackgroundWorker, but then does nothing else - Main exits, and the application is complete. The BackgroundWorker is then shut down at whatever point it's reached. There's nothing wrong with the code it's running - but the app is shutting down without letting it complete.
EDIT: if you want to test this, simply put a Console.ReadLine() at the end of your Main - it'll keep the application alive until you press Enter, and so you should see your thread run until you do.
In addition to Dan Puzey's answer, there's not much sense in assigning an async void method as an event handler for BackgroundWorker, in the first place.
Your worker method bgw_DoWork will return and the background thread will be finished as soon as the execution point hits the first await inside bgw_DoWork. The bot.Update task most likely still will be pending at that point.
You don't need a BackgroundWorker here. The code can be as simple as this:
static void Main(string[] args)
{
DoWorkAsync().Wait();
}
static async Task DoWorkAsync()
{
Weather bot = new Weather();
if (bot.IsRunning)
{
await bot.Update();
}
}
Is it possible to write something in the console while the program is writing something in this console ? It can be useful when you rename, or remove some files, when you do a repetitive action, and the program is writing a lot in the console. Then you will be able to write a command to stop the execution of the repetitive action while the program is continuing to write in the console. I think it's not very clear, well I illustrated you this fact with the code which I think the most apt (but I precise that it doesn't work ;) ). We have 3 classes.
The main class :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApplication1
{
class Program
{
private static bool m_Write;
public static bool write
{
get { return m_Write; }
set { m_Write = value; }
}
static void Main(string[] args)
{
int index = 0;
Console.ReadLine();
m_Write = true;
Reader reader = new Reader();
while (m_Write)
{
index++;
Writer writer = new Writer(index.ToString());
}
}
}
}
The reading class :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;
namespace ConsoleApplication1
{
class Reader
{
private Thread m_Reading_Thread;
private string m_text_To_Read;
public Reader()
{
m_Reading_Thread = new Thread(new ThreadStart(Read));
m_Reading_Thread.Start();
}
public void Read()
{
m_text_To_Read = Console.ReadLine();
if (m_text_To_Read == "Stop")
{
Program.write = false;
}
}
}
}
And the writing class :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;
namespace ConsoleApplication1
{
class Writer
{
private Thread m_Writing_Thread;
private string m_Text_To_Write;
public Writer(string text_To_Write)
{
m_Text_To_Write = text_To_Write;
m_Writing_Thread = new Thread(new ThreadStart(Write));
m_Writing_Thread.Start();
}
public void Write()
{
Console.WriteLine(m_Text_To_Write);
}
}
}
This isn't nearly as complicated as you're trying to make it. In general there are two ways you can do this. You can start a background thread to do the writing, and have the main thread block on the console waiting for the read, or you can have the main thread writing and have the background thread do the read. I like the first solution best:
public class Program
{
private static readonly ManualResetEvent StopWriting = new ManualResetEvent(false);
private static void Main(string[] args)
{
Thread t = new Thread(WriterFunc);
t.Start();
string input;
do
{
input = Console.ReadLine();
} while (input != "stop");
// Tell the thread to stop writing
StopWriting.Set();
// And wait for the thread to exit
t.Join();
}
private static void WriterFunc()
{
int index = 0;
while (!StopWriting.WaitOne(Timeout.Infinite))
{
++index;
Console.WriteLine(index.ToString());
}
}
}
Note that I used a ManualResetEvent here rather than a Boolean flag. An even better solution would be to use a CancellationToken. Using a flag can cause all kinds of interesting problems because the compiler might determine that the variable can't change (it assumes single-threaded access). Your thread might continue running even after the variable is changed.
If you want the main thread to do the writing, and the background thread to do the reading:
public class Program
{
private static readonly ManualResetEvent StopWriting = new ManualResetEvent(false);
private static void Main(string[] args)
{
Thread t = new Thread(ReaderFunc);
t.Start();
int index = 0;
while (!StopWriting.WaitOne(Timeout.Infinite))
{
++index;
Console.WriteLine(index.ToString());
}
// Wait for the background thread to exit
t.Join();
}
private static void ReaderFunc()
{
string input;
do
{
input = Console.ReadLine();
} while (input != "stop");
// Tell the main thread to stop writing
StopWriting.Set();
}
}
Something like this would work:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
var w = new Writer();
var r = new Reader();
while (!r.finish)
{
w.enabled = true;
string k = Console.ReadKey(false).KeyChar.ToString();
w.enabled = false;
string line = k + Console.ReadLine();
r.Read(line);
}
}
}
class Writer
{
public bool enabled = true;
public Writer()
{
var timer = new System.Timers.Timer(1000);
timer.Elapsed += (a, b) =>
{
if(enabled)
Console.WriteLine("Test");
};
timer.Start();
}
}
class Reader
{
public bool finish = false;
public void Read(string line)
{
if (line == "stop")
{
finish = true;
}
}
}
}
Don't worry if the Writer writes above what you are typing, the Console.ReadLine() only considers what you have typed.
In the case of a console application, no two threads can write data to the screen at the exact same time.
AFAIK, in the above answer, the Writes()'s constructor is continuously executed until it finishes running. Then the control will be passed to the Reader(). So I don't think that works for what you need. Correct me if I am wrong.