Polling a email using async await c# - c#

I'm creating a console app that would:
Call a method to check an email account(I've done this step)
Convert the attachemnt to pdf(I've done this step)
Then once the conversion is complete wait 30 seconds
Repeat the previous 3 steps continously
I've done steps 1) and 2) in the ProcessMailMessages() method.
The following code works but I want to know if I am on the right track or is there a better way to poll a email client?
private static int secondsToWait = 30 * 1000;
static void Main(string[] args)
{
bool run = true;
do
{
try
{
Task theTask = ProcessEmailTaskAsync();
theTask.Wait();
}
catch (Exception e)
{
Debug.WriteLine("<p>Error in Client</p> <p>Exception</p> <p>" + e.Message + "</p><p>" + e.StackTrace + "</p> ");
}
GC.Collect();
} while (run);
}
static async Task ProcessEmailTaskAsync()
{
var result = await EmailTaskAsync();
}
static async Task<int> EmailTaskAsync()
{
await ProcessMailMessages();
await Task.Delay(secondsToWait);
return 1;
}
static async Task ProcessMailMessages()
{
...............................................................................
}

Instead of looping in main, you could use a timer. In main, you would set up the timer and then you could just wait on a Console.Readline() to keep the console from closing.
Edit -- here's an example
using System;
namespace ConsoleApplication1
{
class Program
{
private const int MilliSecondsToWait = 30000;
private static System.Timers.Timer EmailTimer;
static void Main(string[] args)
{
EmailTimer = new System.Timers.Timer(MilliSecondsToWait);
EmailTimer.Elapsed += EmailTimer_Elapsed;
EmailTimer.Start();
Console.WriteLine("Press Enter to quit.");
Console.ReadLine();
// if you hit enter, the app will exit. It is possible for the user to exit the app while a mail download is occurring.
// I'll leave it to you to add some flags to control that situation (just trying to keep the example simple)
}
private static void EmailTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
// stop the timer to prevent overlapping email downloads if the current download takes longer than MilliSecondsToWait
EmailTimer.Stop();
try
{
Console.WriteLine("Email Download in progress.");
// get your email.
}
catch (System.Exception ex)
{
// handle any errors -- if you let an exception rise beyond this point, the app will be terminated.
}
finally
{
// start the next poll
EmailTimer.Start();
}
}
}
}

your code works well, its avoiding the use of timers! and also making your code asynchronous with the async/await (TPL). You are on the right track!

This is a gratuitous use of async/await since it is a console app and you are just blocking until the call completes anyway. Might as well just call ProcessMailMessages() from inside your do/while loop and be done with it.

Related

Why is Thread.Sleep() used in following context and how to avoid it?

I'm going through following method which is sending messages over Http.
private static void HTTPProcessQueue()
{
while (true)
{
try
{
Thread.Sleep(10000);
Utils.LogDebug("Msg Queue Check");
while (msgQueue.Count > 0)
{
QueueItem queueItem;
lock (msgQueue)
{
queueItem = msgQueue.Dequeue();
}
if (queueItem != null)
if(!HTTPTransmitEmailItem(queueItem.username, queueItem.filename))
Thread.Sleep(5000);
}
}
catch (Exception ex)
{
}
}
}
In the code above, why are Thread.Sleep(10000) and Thread.Sleep(5000) used in lines 7 and 18?
Also, why is there a while(true) in line 3?
As you requested, here is a slightly better way of doing it:
private static System.Collections.Concurrent.BlockingCollection<MsgType> msgQueue = new System.Collections.Concurrent.BlockingCollection<MsgType>();
private static void AddQueueItems() // simulate adding items to the queue
{
msgQueue.Add(new MsgType());
msgQueue.Add(new MsgType());
msgQueue.Add(new MsgType());
msgQueue.Add(new MsgType());
// when adding is done, or the program is shutting down
msgQueue.CompleteAdding();
}
private static void HTTPProcessQueue()
{
foreach (var queueItem in msgQueue.GetConsumingEnumerable())
{
if (queueItem != null)
{
if (!HTTPTransmitEmailItem(queueItem.username, queueItem.filename))
{
Thread.Sleep(5000);
}
}
}
}
I'd recommending using the async/await pattern with HTTPTransmitEmailItem, and then you can use await Task.Delay(...) instead of Thread.Sleep(...). I've also not included any error checking in this code.
This would then look more like:
private static async Task HTTPProcessQueue()
{
foreach (var queueItem in msgQueue.GetConsumingEnumerable())
{
if (queueItem != null)
{
if (!(await HTTPTransmitEmailItemAsync(queueItem.username, queueItem.filename)))
{
await Task.Delay(5000);
}
}
}
}
But you would have to make a HttpTransmitEmailItemAsync method. Also note that the GetConsumingEnumerable(...) method has an overload which takes a CancellationToken, so you could use this to gain more control over when to end the queue process. You can learn about async/await here.
The Thread.Sleep(10000) is used on line 7 to let the system pause / wait for 10 seconds before it starts the function Utils.LogDebug("Msg Queue Check"); to log the debug information with message "Msg Queue Check". and i believe the Thread.Sleep(5000) is added at the end of loop to create a delay or to wait for 5 seconds before process the next loop.
while(true) is usually used for infinite loop. all method inside this loop will run in loop in infinite time.

Give code limited amount of time to execute within

I have a line of code in an app that looks like this:
string botMessage = chatterBotSession.Think(input);
It's querying a chat bot service and stores the response in botMessage. Sometimes however, the chat bot can take too long to think of a response.
Is there a way I can run the code like normal, but if it doesn't complete in one second cancel it and then run some handler that can alert the user that the service took too long?
Like, normally I might do this:
string botMessage = chatterBotSession.Think(input);
Console.WriteLine("The bot responded with: " + botMessage);
but if the bot is slow the second line doesn't get executed (fast enough). How can I limit the bot's "thinking" time to one second, and run the rest of the code (that would normally run) as soon as it completes if it was successful or run a separate bit of code to display an error message if it hasn't completed.
You can wrap the bot's service call in a Task.Run call and wait for it a predefined amount of time. It would look something like this
static void Main(string[] args)
{
var task = Task.Run(() => chatterBotSession.Think(input));
if (task.Wait(1000))
{
Console.WriteLine(task.Result);
}
else
{
Console.WriteLine("Couldn't get an answer in a timely manner");
}
Console.ReadLine();
}
It is very easy to limit the task execution by using CancellationTokenSource with timeout:
var cancellationToken = new CancellationTokenSource();
var task = chatterBotSession.Think(cancellationToken.Token);
cancellationToken.CancelAfter(TimeSpan.FromMilliseconds(1000)); // cancel after 1sec
await task;
In Think method you should add call to CancellationToken.ThrowIfCancellationRequested
Calling Bot:
static void Main(string[] args)
{
TalkingBot bot = new TalkingBot();
try
{
Console.WriteLine("Thinking started...");
Console.WriteLine(bot.Think("Some input...", 2000));
}
catch (Exception ex)
{
Console.WriteLine("Error: {0}", ex.Message);
}
Console.ReadLine();
}
And Bot itself:
class TalkingBot
{
string input = null;
int timeout = 0;
string asyncThnikResult = null;
public string Think(string input, int timeout)
{
DateTime timeLimit = DateTime.Now.AddMilliseconds(timeout);
this.input = input;
this.timeout = timeout;
System.Threading.Thread thread = new System.Threading.Thread(new System.Threading.ThreadStart(AsyncThnik));
thread.Start();
//wait for result, in this case
while (string.IsNullOrEmpty(asyncThnikResult))
{
if (timeLimit <= DateTime.Now)
{
throw new Exception("Timeout occured!");
}
System.Threading.Thread.Sleep(10);
}
//return result...
return this.asyncThnikResult;
}
/// <summary>
/// Do your thing async...
/// </summary>
void AsyncThnik()
{
string temp = "This value will never be returned due to timeout limit...";
System.Threading.Thread.Sleep(timeout + 1000); //add second to produce timeout...
this.asyncThnikResult = temp;
}
}

C# .Net - How to make application wait until all threads created in Library are finished

I am trying to create a logging library and things are good until the application shutdown is called. When application shutdown is called, any unfinished thread is killed and the specific log is lost.
As of now application exits even before the first 10 threads are complete. I want help on how to make the application wait until all threads created by library are done.
NOTE:
Requirement I got are like this. Modifications should be only in the class 'Logging' since this will be a library and will be provided to end users. Handling of logging issues during app shutdown must be done within it. This is where I have trouble now.
Alternatively a solution like create an event in logging class to trigger all logging complete, and ask user to call app exit on that event is possible, but that I am trying to avoid since it adds that burden to end user and adds complexity for implementations. There is a possibility they may skip it, which I do not want. I am looking for a solution like user should do 'Logging.AddException(....)' and then forget about it.
Please help. Provide comments if you are not clear about the idea.
Here is the full code abstract which you can put into a console application.
Note: Look for comments in CASE 1 and CASE 2.
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace MultithreadKeepAlive
{
class Program
{
static void Main(string[] args)
{
LogLoadTest();
Logging.AddExceptionEntryAsync(new Exception("Last Exception"));
/*
* USE CASE 1: Enable the below lines and you will see how long it is supposed to take.
* Notice that currentDomain_ProcessExit will not trigger if below gets uncommented
*/
//Console.WriteLine("Main thread wait override");
//Console.ReadLine();
}
static void LogLoadTest()
{
//In real world this will be called from any place of application like startup or just after application shutdown is initiated.
//: NOTICE: Unlike the sample here, this will never be on loop and I am not looking for handling multithreads in this class.
// That responsibility I am planning to assign to Logging class.
// AND ALSO the class Logging is going to be in a seperate signed assembly where user of this class ('Program') should not worry about multithreads.
Task t;
for (int i = 0; i < 40; i++)
{
t = Logging.AddExceptionEntryAsync(new Exception("Hello Exception " + i), "Header info" + i);
}
}
}
public class Logging
{
static List<Task> tasks = new List<Task>();
static AppDomain currentDomain;
static Logging()
{
currentDomain = AppDomain.CurrentDomain;
currentDomain.ProcessExit += currentDomain_ProcessExit;
}
public static async Task AddExceptionEntryAsync(Exception ex, string header = "")
{
Task t = Task.Factory.StartNew(() => AddExceptionEntry(ex, header));
tasks.Add(t);
await t;
}
public static void AddExceptionEntry(Exception ex, string header)
{
/* Exception processing and write to file or DB. This might endup in file locks or
* network or any other cases where it will take delays from 1 sec to 5 minutes. */
Thread.Sleep(new Random().Next(1, 1000));
Console.WriteLine(ex.Message);
}
static void currentDomain_ProcessExit(object sender, EventArgs e)
{
Console.WriteLine("Application shutdown triggerd just now.");
Process.GetCurrentProcess().WaitForExit(); //1st attempt.
//Task.WaitAll(tasks.ToArray()); //2nd attempt
while (tasks.Any(t => !t.IsCompleted)) //3rd attempt.
{
}
/* USE CASE 2: IF WORKING GOOD, THIS WILL BE DISPLAYED IN CONSOLE AS LAST
* MESSAGE OF APPLICATION AND WILL WAIT FOR USER. THIS IS NOT WORKING NOW.*/
Console.WriteLine("All complete"); //this message should show up if this work properly
Console.ReadLine(); //for testing purpose wait for input from user after every thread is complete. Check all 40 threads are in console.
}
}
}
You can try
Task.WaitAll(tasks);
This waits for all of the provided Task objects to complete execution.
UPDATE : using async/await
With async and await, we formalize and clarify how asynchronous, non-blocking methods begin and end. An async method can return only void or a Task.
static void Main()
{
// Create task and start it.
// ... Wait for it to complete.
Task task = new Task(AsyncMethod);
task.Start();
task.Wait();
}
public static async void AsyncMethod(){
await AnotherMehod();}
static async Task AnotherMehod() { //TODO}
As of now I myself found a workaround.
/// <summary>
/// Makes the current thread Wait until any of the pending messages/Exceptions/Logs are completly written into respective sources.
/// Call this method before application is shutdown to make sure all logs are saved properly.
/// </summary>
public static void WaitForLogComplete()
{
Task.WaitAll(tasks.Values.ToArray());
}
Step 1: Consider changing to Task.Run() if you do not want the scheduler to be involved. I'm also assuming you want to wait until all async tasks finish.
public static AddExceptionEntry(Exception ex, string header = "")
{
Task t = Task.Factory.StartNew(() => AddExceptionEntry(ex, header));
tasks.Add(t);
WaitForExecutionAsync().ConfigureAwait(true);
}
public static async Task WaitForExecutionAsync()
{
if(tasks.Count >0)
await Task.WhenAll(tasks.ToArray());
// Raise Event.
}
To Block just call this to run sync vs async:
WaitForExecution().GetAwaiter().GetResult();

How to make a pause in a procedure and then return value after it?

I'm working on a C# project, want to make a small pause about 2 seconds inside a procedure.
Actually I have tried to use Invoke, but as you know, we can't use it inside a class this kind of procedure.
Here is my code for more details:
public class GenerateFile
{
public CSPFEnumration.ProcedureResult GenerateFaxFile(string Daftar_No, string Channelno, string NationalCode)
{
string script = string.Format(" DECLARE #RC INT " +
" DECLARE #Daftar_No INT = '{0}' " +
" DECLARE #hokm_type_code INT = 100 " +
" DECLARE #Channelno INT = '{1}' " +
" DECLARE #Id_No BIGINT = '{2}' " +
" EXEC #rc = [dbo].[Hokm_with_type] #Daftar_No, #hokm_type_code, #Channelno, #Id_No ",
Daftar_No,
Channelno,
NationalCode);
try
{
IEnumerable<string> commandStrings = Regex.Split(script, #"^\s*GO\s*$",
RegexOptions.Multiline | RegexOptions.IgnoreCase);
Connect();
foreach (string commandString in commandStrings)
{
if (commandString.Trim() != "")
{
using (var command = new SqlCommand(commandString, Connection))
{
command.ExecuteNonQuery();
}
}
}
DisConnect();
string FaxFilePath = InternalConstant.FaxFilePath + "\\" + string.Format("Lhokm{0}.tif", Channelno);
// I want to make a pause in here without locking UI
if (File.Exists(FaxFilePath))
return CSPFEnumration.ProcedureResult.Success;
else
return CSPFEnumration.ProcedureResult.Error;
}
catch (Exception ex)
{
InternalDatabase.GetInstance.InsertToPensionOrganizationException(ex);
return CSPFEnumration.ProcedureResult.Error;
}
}
}
I have tried await too, but I cant return a proper value. because in this procedure if I use await, the value will return before finishing await.
Edit:
And also I dont want to use Thread.Sleep because it will lock UI.
Thanks for any helping.
Use async await feature :
Mark your method as async .
Add Task.Delay(2000) as the waited task.
public async CSPFEnumration.ProcedureResult GenerateFaxFile(string Daftar_No, string Channelno, string NationalCode)
{
-----
// I want to make a pause in here without locking UI
await Task.Delay(2000);
-----
}
Asking for downvotes:
DoEvents
Warning: Total, Complete and Inexcusably Flagrant Barnyard Programming:
// before call (disable the UI element that called this so it can't re-enter)
DateTime st = DateTime.Now();
while(DateTime.Now.Subtract(st).TotalSeconds<3)
System.Windows.Forms.DoEvents();
// after call (re-enable UI element)
This will appear to work. No responsibility if people point and laugh.
Hey, you asked!
You can look around Task.Delay() it will not block current thread and continue execution after number of milliseconds.
Exmaple usage from msdn:
Stopwatch sw = Stopwatch.StartNew();
var delay = Task.Delay(1000).ContinueWith(_ =>
{ sw.Stop();
return sw.ElapsedMilliseconds; } );
Console.WriteLine("Elapsed milliseconds: {0}", delay.Result);
// The example displays output like the following:
// Elapsed milliseconds: 1013
Or maybe look around Timer class.
I can see it working with events or Tasks (if you cannot use async / await). This is how to create event. We can use separate Thread to check if file is created and fire event if it is:
public class FileGenEventArgs : EventArgs
{
public string ProcedureResult { get; set; }
}
public class GenerateFile
{
public event EventHandler<FileGenEventArgs > fileCreated;
public GenerateFile()
{
// subscribe for this event somewhere in your code.
fileCreated += GenerateFile_fileCreated;
}
void GenerateFile_fileCreated(object sender, FileGenEventArgs args)
{
// .. do something with args.ProcedureResult
}
private void FileCheck()
{
Thread.Sleep(2000); // delay
fileCreated(this, new FileGenEventArgs()
{
ProcedureResult = File.Exists(FaxFilePath) ?
CSPFEnumration.ProcedureResult.Success :
CSPFEnumration.ProcedureResult.Error
});
}
public void GenerateFaxFile(string Daftar_No, string Channelno, string NationalCode)
{
try
{
// this .Sleep() represents your sql operation so change it
Thread.Sleep(1000);
new Thread(FileCheck).Start();
}
catch (Exception ex)
{
InternalDatabase.GetInstance.InsertToPensionOrganizationException(ex);
}
}
}
Pros :
Pause that you wanted
Doesn't block the UI thread.
Event-based approach (which is proper way of dealing with this kind of problems)
Cons :
Requires to refactor your code
The most easy thing to wait while keeping the UI responsive is using async-await.
To do this, you must declare your function async, and return Task instead of void and Task<TResult> instead of TResult:
public async Task<CSPFEnumration.ProcedureResult> GenerateFaxFile(
string Daftar_No,
string Channelno,
string NationalCode)
{
// do your stuff,
}
Now whenever you do something that takes some time, use the async version of the function to start the process. While this process is running, you can do other stuff. When you need the result await for the task, and you get the void if the async returns Task, or the TResult if the async returns Task<TResult>
public async Task<CSPFEnumration.ProcedureResult> GenerateFaxFile(
string Daftar_No,
string Channelno,
string NationalCode)
{
IEnumerable<string> commandStrings = Regex.Split(
script, #"^\s*GO\s*$", RegexOptions.Multiline | RegexOptions.IgnoreCase);
Connect();
foreach (var commandString in commandStrings)
{
if (commandString.Trim() != "")
{
using (var command = new SqlCommand(commandString, Connection))
{
Task<int> task = command.ExecuteNonQueryAsync();
// while the command is being executed
// you can do other things.
// when you need the result: await
int result = await task;
// if useful: interpret result;
}
}
}
DisConnect();
... etc.
}
Every function that calls an async function should be declared async
every async function returns Task instead of void and Task<TResult> instead of TResult
There is only one exception: the event handler may return void.
Example of async event handler:
private async void OnButton1_Clicked(object sender, ...)
{
var task = GenerateFaxFile(...);
// while the fax file is generated do some other stuff
// when you need the result:
var procedureResult = await task;
Process(procedureResult);
}
Note that everything is processed by the UI thread. The only difference is that as soon as anything time consuming happens, the process doesn't have a busy wait, but processes UI input.
The above is enough to keep your UI responsive. You said you wanted to know how to wait some time. From the rest of your question I understand that you meant: how to interrupt the procedure while it is waiting for something, so the UI can do other thing. If you really need to wait some time while keeping the UI responsive, use Task.Delay(TimeSpan).
Eric Lippert (thanx Eric!) explained async-await as follows in Stackoverflow - async/await - Is this understanding correct?
Suppose for breakfast you have to toast bread and cook eggs. There are several scenarios for it:
Start toasting bread. Wait until it is finished. Start cooking eggs, wait until it is finished. Synchronous processing. While you are waiting for the bread to toast you can't do anything else.
Start toasting bread, while the bread is being toasted start cooking eggs. when the eggs are cooked wait until the bread finished toasting. This is called Asynchronous, but not concurrent. It is done by the main thread and as long as this thread does something, the main thread can't do anything else. But while it is waiting it has time to do other things (make some tea for instance)
Hire cooks to toast the bread and cook the eggs. Wait until both are finished. Asynchronous and concurrent: the work is done by different threads. This is the most expensive because you have to start new threads.
Finally a note about your exception handling
Do you notice that if an exception occurs you don't disconnect?. The proper way to make sure that disconnect is always called is the following:
try
{
Connect();
... do other stuff
}
catch (Exception exc)
{
... process exception
}
finally
{
Disconnect();
}
The finally part is always executed, regardless of any exception being thrown or not.
You can use simple Thread Pool to archive this. However your return has to do asynchronously so it doesn't lockup the gui.
public void GenerateFaxFile(string Daftar_No, string Channelno,
string NationalCode, Action<CSPFEnumration.ProcedureResult> result)
{
ThreadPool.QueueUserWorkItem(o =>
{
string script = "your script";
try
{
// more of your script
// I want to make a pause in here without locking UI
while (true)
{
// do your check here to unpause
if (stopMe == true)
{
break;
}
Thread.Sleep(500);
}
if (File.Exists(FaxFilePath))
{
result(CSPFEnumration.ProcedureResult.Success);
return;
}
else
{
result(CSPFEnumration.ProcedureResult.Error);
}
}
catch (Exception ex)
{
InternalDatabase.GetInstance.InsertToPensionOrganizationException(ex);
result(CSPFEnumration.ProcedureResult.Error);
return;
}
});
}
public void HowToUseMe()
{
GenerateFaxFile("", "", "", result => {
if (result == CSPFEnumration.ProcedureResult.Error)
{
// no good
}
else
{
// bonus time
}
});
}
You should use the old good background thread (see answer written by FabJan) or you can use async and await with synchronization context:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private async void buttonStart_Click(object sender, EventArgs e)
{
await progressBar1.DoProgress(2000);
Trace.WriteLine("Done");
MessageBox.Show("Done");
}
private void buttonMoveButton1_Click(object sender, EventArgs e)
{
//to prove UI click several times buttonMove while the task is ruunning
buttonStart.Top += 10;
}
}
public static class WaitExtensions
{
public static async Task DoProgress(this ProgressBar progressBar, int sleepTimeMiliseconds)
{
int sleepInterval = 50;
int progressSteps = sleepTimeMiliseconds / sleepInterval; //every 50ms feedback
progressBar.Maximum = progressSteps;
SynchronizationContext synchronizationContext = SynchronizationContext.Current;
await Task.Run(() =>
{
synchronizationContext.OperationStarted();
for (int i = 0; i <= progressSteps; i++)
{
Thread.Sleep(sleepInterval);
synchronizationContext.Post(new SendOrPostCallback(o =>
{
Trace.WriteLine((int)o + "%");
progressBar.Value = (int)o;
}), i);
}
synchronizationContext.OperationCompleted();
});
}
}
It could appear that MessageBox done Shows before the ProgressBar is on its Maximum. I blame for this magic animation of progressBar in Windows 8. Please correct me if I am wrong.

How to know if Task or Void method is still running when using Async

I am trying to use async and await and my problem is that it wont wait for the background process to finish. Maybe you are wondering why don't I just run the application synchronously?
I'm trying finish a part of my task ASAP and the rest can be awaited as shown in this example.
Thank you for the help guys! =)
class Program
{
static void Main(string[] args)
{
Run();
//Problem or Maybe Not? Needs this
//So that my application won't close immediately
Console.ReadLine();
}
private async static void Run()
{
Task<bool> TBool = ProcessRecords();
if (await TBool)
{
//Problem #1 This Line Doesn't Show
Console.WriteLine("End of Code");
//SHould be safe to close the application by Now
//But goes through here not waiting for the return
//of the last process.
Environment.Exit(0);
//My temporary solution is to indicate a Task.Delay(80000)
//to make sure that all the logging in the background
//are all done. I dont know if there is a function that shows
//that there are task running on the background or any
//other workaroung will help. =) thanks
}
}
private async static Task<bool> ProcessRecords()
{
Task newTask = null;
//Loop through all the records and send
//all the records to MQ ASAP
for (int x = 0; x < 10; x++)
{
//I wont wait for this Task so
//I can send the next record
newTask = SendToMQ(x);
}
//I only need to wait for the last Task to
//indicate that I can exit the system
//as soon as it finish
//Problem #2 The Console.WriteLine doesnt show the last record.
await newTask;
return true;
}
private async static Task SendToMQ(int count)
{
//actual sending of message (Important)
await Task.Delay(1000);
//Process of Logging Connect to DB etc, (Not so Important, but takes most of the time)
await LoggingRecord();
Console.Clear();
Console.WriteLine("Done Processing " + count.ToString() + " records");
}
//Logging of each record
private async static Task LoggingRecord()
{
await Task.Delay(5000);
//Problem #3 This Line Doesn't Show
Console.WriteLine("Last Log Finished");
}
}
You should use await whenever possible:
await Run();
However, in this case you cannot, so you must use Wait
static void Main(string[] args)
{
Run().Wait();
//Problem or Maybe Not? Needs this
//So that my application won't close immediately
//Console.ReadLine();
}
// note the return type is Task
private async static Task Run()
{
...
}
In ProcessRecords() you have the following line - I am not quite sure what you mean, so I didn't address it:
//Problem #2 The Console.WriteLine doesnt show the last record.
The above prints out
Done Processing 9 records
End of Code

Categories

Resources