Sharp Always
Sharp Always

Reputation: 61

How to run an infinite thread?

I'm trying to run a Thread infinitely, but it's not working ...

Follow the code:

namespace BTCPrice
{
    public static class Price
    {
        private static volatile bool _shouldStop = false;

        public static void RequestStop()
        {
            _shouldStop = true;
        }

        public static void Refresh(out string value, int tipo = 0, string source = "https://www.mercadobitcoin.net/api/")
        {
            while (_shouldStop == false)
            {

                JavaScriptSerializer serializer = new System.Web.Script.Serialization.JavaScriptSerializer();

                WebClient cliente = new WebClient();

                string json = cliente.DownloadString(string.Format("{0}/{1}/{2}", source, "BTC", "ticker"));

                JObject j = JObject.Parse(json);

                switch (tipo)
                {
                    //Get High Price
                    case 0:
                        value = j["ticker"]["high"].ToString();
                        break;

                    //Get Low Price
                    case 1:
                        value = j["ticker"]["low"].ToString();
                        break;

                    default:
                        value = "default";
                        break;

                }

                Thread.Sleep(1000);
            }

            value = "Stopped";
        }
    }
}

On Start:

string result = "";
Thread workerThread = new Thread(() => {
    Price.Refresh(out result);

    MessageBox.Show(result);

    Invoke(textBox1, result);

    Thread.Sleep(1000);
});

No exception occurs ... as long as I remove the While (_shouldStop == false) class the code works perfectly. However, I would like that, while the program is open, it executes the code and updates the textbox with the value that I get by the API.

result without While(_shouldStop == false) in class:

Expected Result with While

Upvotes: 1

Views: 6861

Answers (2)

Enigmativity
Enigmativity

Reputation: 117010

You really shouldn't be using threads these days when there are excellent alternatives that handle all of the mess for you.

I'd suggest using Microsoft's Reactive Framework (aka "Rx"). Just NuGet "System.Reactive", "System.Reactive.Windows.Forms" (Windows Forms), "System.Reactive.Windows.Threading" (WPF).

Then you can do this:

int tipo = 0;
string source = "https://www.mercadobitcoin.net/api/";

string url = string.Format("{0}/{1}/{2}", source, "BTC", "ticker");

IObservable<string> feed =
    from n in Observable.Interval(TimeSpan.FromSeconds(1.0))
    from json in Observable.Using<string, WebClient>(() => new WebClient(), cliente => cliente.DownloadStringTaskAsync(url).ToObservable())
    let j = JObject.Parse(json)
    let high = j["ticker"]["high"].ToString()
    let low = j["ticker"]["low"].ToString()
    select tipo == 0 ? high : (tipo == 1 ? low : "default");

IDisposable subscription =
    feed
        .ObserveOn(this); // for Windows Forms OR .ObservableOnDispatcher() for WPF
        .Subscribe(value =>
        {
            /* Do something with `value` */
        });

You'll now get a steady stream of the string value every second. A thread is started automatically and the results are automatically pasted to the UI thread.

When you want to stop the feed producing values just call subscription.Dispose();.

This code entirely replaces your Price class.

Upvotes: 4

Sam Marion
Sam Marion

Reputation: 690

Change your while loop in Price.Refresh to inside the thread. Have Price.Refresh return a string instead.

Thread workerThread = new Thread(() => {
while (true)
{ 
    String result = Price.Refresh();

    MessageBox.Show(result);

    Invoke(textBox1, result);

    Thread.Sleep(1000); 
});

I agree with Scott Chamberlain in that you should use a timer instead and rewrite this but this will work for you.

Upvotes: 2

Related Questions