I must say that with

webbrowser.Navigate("tra.ta"); 

There are no problems. The problems start from this moment:

 webbrowser.Document.GetElementById("switch_to_login_button").InvokeMember("click"); 

and so on. Tell me how to use this component in the background, and it is very desirable that the work was visible in the GUI and it was alive. From what I tried: 1. Work in backgroundworker, with a parameter

  CheckForIllegalCrossThreadCalls = false. 

2. Work there, using

 this.BeginInvoke(new Action(() => 

It did not fit, because there was no point, all the same, the form is hanging. 3. Create a new instance of WebBrowser in backgroundworker. And also in the stream created like this:

 System.Threading.Thread t = new System.Threading.Thread(() => { WebBrowser wb = new WebBrowser(); wb.Navigate("https://freebitco.in/"); Thread.Sleep(5000); wb.Document.GetElementById("login_form_btc_address").SetAttribute("value", login.Text); }); t.ApartmentState = System.Threading.ApartmentState.STA; t.Start(); 

4. The attempt to install Awesomium, which failed, because VS did not want to accept the assembly, for some unknown reason.

If I still remember what I tried, I will write, because I tried a bunch of methods, but I did not find a solution. I fight all day.

UPD: Here is the code that I use in the thread (both Thread and BackgroundWorker:

  System.Threading.Thread t = new System.Threading.Thread(() => { this.BeginInvoke(new Action(() => { mainweb.Document.GetElementById("menu_drop").InvokeMember("click"); mainweb.Document.GetElementById("drop1").Children[1].Children[0].InvokeMember("click"); Thread.Sleep(2000); int losts = 0; int wins = 0; do { mainweb.Document.GetElementById("double_your_btc_stake").SetAttribute("value", num.Text); if (play(Convert.ToBoolean(button))) { wins++; if (button == 0) { button = 1; } else { button = 0; } } else { losts++; num.Text = Convert.ToString(decimal.Parse(Convert.ToString((decimal.Parse(num.Text) * 2)), NumberStyles.Float)); mainweb.Document.GetElementById("double_your_btc_stake").SetAttribute("value", num.Text); } l_losts.Text = "Проигрышей: " + losts; l_wins.Text = "Выигрышей: " + wins; } while (losts < Convert.ToInt32(max_losts.Text) && wins < Convert.ToInt32(max_wins.Text)); })); }); t.ApartmentState = System.Threading.ApartmentState.STA; t.Start(); 
  • In theory, all calls to controls should be in the UI thread. CheckForIllegalCrossThreadCalls = false - this somehow sounds very wrong. And what does “form still hang” mean? Here, please, more. - VladD 4:04 pm
  • Corrected the start-post. When executing this code, the form hangs. - Andrei Tsapenko
  • Well, Thread.Sleep(2000); - not surprising. - VladD

2 answers 2

You are doing something wrong. You start the stream, and then from this stream, you again flip the code into the UI stream. It is like making all actions in one thread.

Since you need a pause of 2 seconds (do you really need it? What are you really waiting for?), You need to make an asynchronous function.

 async Task Do() { var doc = mainweb.Document; doc.GetElementById("menu_drop").InvokeMember("click"); doc.GetElementById("drop1").Children[1].Children[0].InvokeMember("click"); await Task.Delay(2000); int loses = 0, wins = 0; do { doc.GetElementById("double_your_btc_stake").SetAttribute("value", num.Text); // button надо превратить в bool if (play(button)) { wins++; button = !button; } else { loses++; // вам точно нужен decimal? o_O // ну decimal.Parse после Convert.ToString вам точно не нужно decimal score = decimal.Parse(num.Text); score *= 2; num.Text = score.ToString(); doc.GetElementById("double_your_btc_stake").SetAttribute("value", num.Text); } l_losts.Text = "Проигрышей: " + loses; l_wins.Text = "Выигрышей: " + wins; } while (losts < int.Parse(max_losts.Text) && wins < int.Parse(max_wins.Text)); } 

If your play function is blocking, redo it in Task<bool> and call it via await .

(Generally, there is something wrong with the types of variables, revise them. You have too many back and forth conversions.)

  • I am just beginning to learn this language, and indeed, in essence, to program, therefore such answers are important. I did as I could, using Google. And those conversions were needed to convert the number 0.00000001 from the string, multiply and then transfer back to the string, and additional conversions were needed to get rid of the engineering form. A pause is not really needed, made for security reasons, so that the page is loaded. I'll figure it out now with Task <bool> - Andrei Tsapenko
  • Thank you so much, figured out this issue! - Andrei Tsapenko
  • You are welcome! Owning async / await is very important, all modern asynchronous C # programming is built on it. - VladD
  • So many ways to create multithreading. :) And why is MSDN positioning backgroundworker as the most priority way? Or am I misinterpreting the words asynchrony and multithreading? - Andrei Tsapenko
  • @Andrey Tsapenko: It was so long ago. Starting in C # 5, the priority method is async / await. - VladD

Your code throws all the work into the main thread (by calling BeginInvoke ).

Everything from the string

 mainweb.Document.GetElementById("menu_drop").InvokeMember("click"); 

and until the end of the while is executed in the main thread. Until the cycle is completed to the end - the main stream is busy, no redrawing takes place and everything hangs.

You need to break the code into small pieces and execute them little by little, so that they can work on rendering between them. Or somehow allow the application to respond to events during the loop. The two most simple options:

  1. Use timer. What you have now in the body of the loop is transferred to the timer handler. Those. instead of a loop, you will get your code for betting every X milliseconds, with a drawing between them.
  2. Or just insert in the code of the Application.DoEvents() call loop. Each such call will allow the application to handle the accumulated events, including drawing and clicks.