Асинхронное многопоточное значение bool в C #

1

Я пытаюсь создать кнопку, которая отображает загрузочный круг и загружает некоторые данные в приложение С#.

У меня есть логическое значение " Loading которое отслеживает состояние текущих данных, которые загружаются.

У меня есть делегат под названием LoadHandler который возвращает логическое значение, основанное на завершении загрузки или нет, у меня также есть событие, которое может быть подписано в отдельном классе, который принимает подпись LoadHandler и обрабатывает фактическую загрузку.

У меня есть private Load() функция private Load() которая вызывается, когда в базовом классе вызывается обработчик событий для ввода, который вызывается в new Thread.

Здесь код для класса LoadEntry (помните, что это всего лишь кнопка, которая отображает загрузочный круг при попадании и делегирует загрузку в отдельный класс)

public class LoadingEntry : ButtonEntry
{
    private readonly object objLock = new object(); 

    /// <summary>
    /// The loading circle texutre
    /// </summary>
    Texture2D loadingReticle; 

    /// <summary>
    /// Tracks the rotation of the loading reticle.
    /// </summary>
    float loadingRotation;

    /// <summary>
    /// Tells whether we are loading or not
    /// </summary>
    public bool Loading { get; private set; } 

    public LoadingEntry(string buttonText)
        : base(buttonText)
    {

    }

    /// <summary>
    /// Handler that will return true when loading information is complete
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    /// <returns>True if loading is complete</returns>
    public delegate bool LoadHandler(object sender, EventArgs e); 

    /// <summary>
    /// The LoadHandler event that should be subscribed to in a menu class 
    /// </summary>
    public event LoadHandler onLoad;

    private void Load()
    {
        if (onLoad != null)
        {
            lock (objLock)
            {
                Loading = true;
                while (true)
                {
                    Loading = onLoad(this, EventArgs.Empty);
                    if (!Loading)
                        break;
                }
            }
        }
    }

    protected internal override void OnSelectEntry(PlayerIndex playerIndex)
    {
        Thread t = new Thread(new ThreadStart(Load));
        t.Start(); 
        base.OnSelectEntry(playerIndex);
    }

    public override void Draw(MenuScreen screen, bool isSelected, GameTime gameTime, bool fade)
    {
        if (Loading)
        {
            loadingReticle = screen.ScreenManager.LoadingReticle; 

            Vector2 origin = new Vector2(loadingReticle.Width / 2, loadingReticle.Height / 2); 
            loadingRotation += 0.01f;

            screen.ScreenManager.SpriteBatch.Draw(loadingReticle, position, null, Color.White, loadingRotation, origin, 1f, SpriteEffects.None, 1f); 
        }
        else base.Draw(screen, isSelected, gameTime, fade);
    }

Базовый класс ButtonEntry не должен быть важен.

И вот то, что подписано на onLoad в другом классе: (просто для практики, это будет где будет загружен фактический код загрузки)

    int sampleTics = 0; 
    bool sampleLoad_onLoad(object sender, System.EventArgs e)
    {
        sampleTics++;
        if (sampleTics < 1000)
            return true;

        return false; 
    }

Мой вопрос: правильно ли использую mulit-threading? Код даже не отображает круг, я еще не много тестировал, потому что я ложился спать. Необходим ли замок в этой ситуации? Есть ли лучший способ сделать это, что я не вижу?

Теги:
delegates
multithreading
boolean
locking

2 ответа

0
Лучший ответ

Оказывается, мне нужно было вызвать Thread.Sleep(1); чтобы увидеть результаты. Здесь полный код:

private void Load()
    {
        if (onLoad != null)
        {
            loading = true;
            while (true)
            {
                loading = onLoad(this, EventArgs.Empty);
                if (!loading)
                    break;

                Thread.Sleep(1); 
            }
        }
    }
1

bool является потокобезопасным в соответствии с документацией. См. Это сообщение для аналогичного вопроса. Как было предложено по почте, вам также необходимо объявить переменную boolle переменной volatile чтобы ее значение не было кэшировано. Вы не можете объявлять свойства volatile поэтому вам нужно будет добавить свойство backing и объявить, что это изменчиво.

  • 0
    Это хорошая информация и кое-что, что я пропустил, но, как оказалось, мне нужно было вызвать Thread.Sleep(1); чтобы он мог выйти из цикла, загрузка немного дольше, но он добился цели

Ещё вопросы

Сообщество Overcoder
Наверх
Меню