C#中的异步MultiThreaded bool值

时间:2014-05-18 09:39:54

标签: c# multithreading delegates locking boolean

我正在尝试构建一个显示加载圈的按钮,并在C#应用程序中加载一些数据。

我有一个名为Loading的布尔值,用于跟踪正在加载的当前数据的状态。

我有一个名为LoadHandler的委托,它根据加载是否完成返回一个布尔值,我还有一个事件可以在一个单独的类中订阅,该类接受LoadHandler签名并处理实际加载。

我有一个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; 
    }

我的问题是我是否正确使用多线程?代码甚至没有显示圆圈,我还没有做太多测试,因为我要睡觉了。在这种情况下锁定是否必要?有没有更好的方法来做到这一点,我没有看到?

2 个答案:

答案 0 :(得分:1)

根据{{​​3}},

bool是线程安全的。有关类似问题,请参阅documentation。根据帖子的建议,您还需要声明布尔变量volatile,以便不缓存其值。您无法声明属性volatile,因此您需要添加支持属性并声明该属性。

答案 1 :(得分: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); 
            }
        }
    }