My Code:
ConcurrentQueue<string> concurrentQueue = new ConcurrentQueue<string>(); private void Form1_Load(object sender, EventArgs e) { try { var task1 = Task.Run(() => GetMessages()); var task2 = Task.Run(() => GetOrderBookData()); UpdateOrderBook(); } catch(Exception ex) { MessageBox.Show(ex.Message); } } private void GetMessages() { var w = new WebSocketConfiguration(); //class to connect o websocket to get messages w.OnWSOpen += w_OnWSOpen; w.OnWSMessage += w_OnWSMessage; w.OnWSError += w_OnWSError; w.OnWSClose += w_OnWSClose; w.SetWebSocketSharpEvents(); // connect to websocket } void w_OnWSMessage(string message) { this.Invoke(new MethodInvoker(delegate() { listBox1.Items.Add(message); concurrentQueue.Enqueue(message); // To refresh the GUI simultaneously as the background process progresses Application.DoEvents(); })); } private void UpdateOrderBook() { if (!concurrentQueue.IsEmpty) { string jsonString; while (concurrentQueue.TryDequeue(out jsonString)) { } } }
Edit:
private void GetOrderBookData() { var OrderList = new List<string>(); // Add items using Add method OrderList.Add("order1"); OrderList.Add("order2"); OrderList.Add("order3"); OrderList.Add("order4"); OrderList.Add("order5"); dgOrders.DataSource = OrderList; }
In my code UpdateOrderBook is called first and then GetMessages()
is called. I want GetMessages()
to keep running and once started it should call GetOrderBookData()
to fill the values in a grid. Now I want to read messages from the queue and update the grid by calling UpdateOrderBook()
.
How do I make it asynchronous?
EDIT:
GetMessages() will send me more orders which I have to add/delete in the grid.
EDIT2
Steps: I want to call
(1) GetMessages()
this will keep bringing the messages in separate thread
(2) Once the messages starts coming in (1) then call the GetOrderData()
this will fetch the order details and insert them in datagrid and the its task is finished here
(3) UpdateOrderBook()
this will now update the existing datagrid (which already has some data from step 2). Here in this method I want to check the queue and have to iterate the concurrentqueue then do some processing and then insert that record in the existing grid.
Hope this is clear now. The two process (1,3) would run asynchronously but for the first time it should process in above order.
I got stuck in making them run asynchronously.
4 Answers
Answers 1
Asynchronous methods that you define by using async and await are referred to as async methods. The good thing is that you can rewrite your code to tell the compiler to treat those methods as async. Now, you should be aware that if you don't call the await method inside an asynchronous methods it will not tell the compiler to stop the execution on that point and continue later. They good news is that you can execute the await over your method even if they return just void(Task)
What about this.
TaskFactory.StartNew Method (Action) Creates and starts a task. Parameters:action Type: System.Action The action delegate to execute asynchronously.Documentation Here
Task task1 = Task.Factory.StartNew(GetMessages); Task task2 = Task.Factory.StartNew(GetOrderBookData).ContinueWith(t => UpdateOrderBook()); Task.WhenAll(task1, task2).Wait();
This is another approach too
void Main() { var cancelSource = new CancellationTokenSource(); Action action1 = async () => { await GetMessages(); }; Action action2 = async () => { //wait for filling the GetOrderBookData await GetOrderBookData(); //on this point you should have the data to refresh on the grid UpdateOrderBook(); }; Task task1 = Task.Factory.StartNew(action1, cancelSource.Token); Task task2 = Task.Factory.StartNew(action2, cancelSource.Token); //when you want to cancel the task just call Cancel over cancelSource => cancelSource.Cancel(); Task.WhenAll(task1, task2).Wait(); } //Be sure to mark your methods with the async keyword private async Task UpdateOrderBook() { ... } private async Task GetOrderBookData() { .... } private async Task GetMessages() { .... }
Answers 2
Maybe this will help:
using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; using System.Windows.Forms; namespace WindowsFormsApplication1 { public partial class Form1 : Form { ConcurrentQueue<string> messageQueue = new ConcurrentQueue<string> (); public Form1 () { InitializeComponent (); } private async void Form1_Load (object sender, EventArgs e) { var task1 = GetMessages (); var task2 = Task.Factory.StartNew (GetOrderBookData); dgOrders.DataSource = await task2; await Task.WhenAll (task1, task2); UpdateOrderBook (); } public async Task GetMessages () { for (int i = 0; i < 10; i++) { string message = await Task.Run (() => GetMessage (i)); messageQueue.Enqueue (message); listBox1.Items.Add (message); } } private string GetMessage (int id) { Thread.Sleep (500); // simulate work return "some-message-" + id; } private IReadOnlyList<string> GetOrderBookData () { Thread.Sleep (2000); // simulate work return new List<string> { "order 1", "order 2", "order 3" }; } private void UpdateOrderBook () { string message = null; string jsonString; while (messageQueue.TryDequeue (out jsonString)) { message += jsonString + "\r\n"; } MessageBox.Show (message); } } }
Answers 3
Try this.
private void Form1_Load(object sender, EventArgs e) { try { //get messages asynchronously Task getMessagesTask = new Task(GetMessages); getMessagesTask.Start(); GetOrderBookData(); Task updateTask = new Task(UpdateOrderBook); //check if concurrent queue has items if(!concurrentQueue.IsEmpty) { updateTask.Start(); } } catch (Exception ex) { MessageBox.Show(ex.Message); } }
Answers 4
To make this code asynchronous you have to do something like this:
private async void Form1_Load(object sender, EventArgs e) { var t1 = Task.Run(() => GetMessages()); var t2 = Task.Run(() => GetOrderBookData()); var t3 = Task.Run(() => UpdateOrderBook()); await Task.WhenAll(t1, t2, t3); }
Now, there is a still a problem with your code in that it seems that UpdateOrderBook
is dependent on the result of GetMessages
. It seems that you are doing some sort of wait and check type loop in UpdateOrderBook
. That's not a great idea.
Also the code for GetOrderBookData
isn't even in your question.
It would be awesome to have the three methods fully implemented and posted in your question so that we can see how this all hangs together and then we could provide a better solution.
0 comments:
Post a Comment