C# 使用'是否安全;锁';在计时器滴答声事件中?

C# 使用'是否安全;锁';在计时器滴答声事件中?,c#,winforms,timer,locking,deadlock,C#,Winforms,Timer,Locking,Deadlock,我想知道这种方法是否有可能导致僵局 示例代码:单击应用程序按钮时,将创建作业对象并将其添加到作业列表中。添加代码受“锁定”保护。然后在计时器滴答声事件中,我想从列表中删除已完成的作业——在计时器事件中锁定列表 所以问题是,如果用户按下添加作业按钮,而计时器事件使用了锁,这个应用程序会死锁吗 计时器是Windows窗体计时器 public partial class Form1 : Form { object listLock = new object(); List<Job

我想知道这种方法是否有可能导致僵局

示例代码:单击应用程序按钮时,将创建作业对象并将其添加到作业列表中。添加代码受“锁定”保护。然后在计时器滴答声事件中,我想从列表中删除已完成的作业——在计时器事件中锁定列表

所以问题是,如果用户按下添加作业按钮,而计时器事件使用了锁,这个应用程序会死锁吗

计时器是Windows窗体计时器

public partial class Form1 : Form
{
    object listLock = new object();
    List<Job> jobsList = new List<Job>();
    public Form1()
    {
        InitializeComponent();
        timer1.Start();
    }

    private void timer1_Tick(object sender, EventArgs e)
    {
        Job aJob;
        lock(listLock)
        {
            for (int i = jobsList.Count - 1; i > -1; i--)
            {
                aJob = jobsList[i];
                if (aJob.IsCompleted)
                {
                    jobsList.RemoveAt(i);
                }

            }
        }

    }

    private void button1_Click(object sender, EventArgs e)
    {
        lock (listLock)
        {
            Job aJob = new Job();
            jobsList.Add(aJob);
        }

    }
}

//=====================================
  class Job
    {
        bool isCompleted = false;

        public bool IsCompleted
        {
            get { return isCompleted; }
            set { isCompleted = value; }
        }

        public Job()
        {
            // do some work then mark complete
            IsCompleted = true;
        }
}
公共部分类表单1:表单
{
object listLock=新对象();
列表作业列表=新列表();
公共表格1()
{
初始化组件();
timer1.Start();
}
私有无效计时器1_刻度(对象发送方,事件参数e)
{
一份工作;
锁(列表锁)
{
对于(int i=jobsList.Count-1;i>-1;i--)
{
aJob=工作列表[i];
如果(某项工作已完成)
{
作业列表移除(i);
}
}
}
}
私有无效按钮1\u单击(对象发送者,事件参数e)
{
锁(列表锁)
{
Job aJob=新作业();
工作列表。添加(aJob);
}
}
}
//=====================================
班级作业
{
bool isCompleted=false;
公共图书馆完工了
{
获取{return isCompleted;}
设置{isCompleted=value;}
}
公职()
{
//做一些工作,然后标记完成
IsCompleted=真;
}
}
计时器事件(来自Windows窗体计时器)从主消息循环中调度。因此,它们永远不会与任何其他UI事件的处理程序重叠


按下按钮将进入消息队列,并在计时器计时处理程序完成后进行处理。(因此,您不需要锁定仅由UI事件处理程序操作的数据结构,因为它们将按队列顺序顺序运行)

好的,谢谢Ben。如果另一个Windows窗体调用此窗体上的公共方法以将项目添加到此列表中,该怎么办?这仍然是死锁安全的吗?@LTDan:只要它们是从单个消息循环控制的(
Application.Run
,在
Main
方法中),那么它们就共享一个队列并按顺序运行,没有争用条件。只有从另一个线程访问数据结构,才会出现数据冲突。