Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/visual-studio-2010/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 发布版本与调试版本运行方式不同_C#_Visual Studio 2010 - Fatal编程技术网

C# 发布版本与调试版本运行方式不同

C# 发布版本与调试版本运行方式不同,c#,visual-studio-2010,C#,Visual Studio 2010,对不起,我很困惑。我们有一个向硬件发送命令的过程,这个过程会被淹没。我创建了一个简单的解决方案,在每发送100次之后,它会暂停1秒,然后继续处理。在调试模式下运行,这完全解决了我们遇到的所有问题。然而,当我将这个解决方案编译成一个发布版本时,我的计时器方法似乎永远无法运行 在下面的代码中,我有一个简单的while循环,循环直到bool为true。(我不想使用sleep,因为我不想线程变得无响应) foreach(ds.Tables[0].Rows中的数据行) { stringbadge=Data

对不起,我很困惑。我们有一个向硬件发送命令的过程,这个过程会被淹没。我创建了一个简单的解决方案,在每发送100次之后,它会暂停1秒,然后继续处理。在调试模式下运行,这完全解决了我们遇到的所有问题。然而,当我将这个解决方案编译成一个发布版本时,我的计时器方法似乎永远无法运行

在下面的代码中,我有一个简单的while循环,循环直到bool为true。(我不想使用sleep,因为我不想线程变得无响应)

foreach(ds.Tables[0].Rows中的数据行)
{
stringbadge=Database.GetString(第行,“Badge”);
如果(徽章长度>0)
{
if(计数<控制器最大负载)
{
如果(processed==100)//每下载100次,暂停一秒钟
{
已处理=0;
StartTimer();
而(!isWaitOver)
{
}
控制器。PostRecordsDownloadeof(“徽章”,计数);
}
如果(下载(徽章,假))
{
计数++;
处理++;
}
}
其他的
丢弃的++;
}
TotalCount++;
}
私有void StartTimer()
{
//创建一个间隔为1秒的计时器。
aTimer=新系统计时器计时器(1000);
//连接计时器的已用事件。
aTimer.appeased+=OnTimedEvent;
aTimer.AutoReset=true;
aTimer.Enabled=true;
isWaitOver=false;
}
私有void OnTimedEvent(对象源,System.Timers.ElapsedEventArgs e)
{
isWaitOver=true;
aTimer.Enabled=false;
}
任何人都能看到while循环在释放模式下运行时被无限卡住的原因吗?另外,如果有人看到更好的解决方案,请告诉我。但是我必须使用VS2010


感谢阅读。

您的代码中似乎有竞争条件。启动计时器首先启用计时器,然后将
isWaitOver
设置为
false
。运行时,
OnTimedEvent
会将
isWaitOver
设置为
true
。这有点不太可能,但在繁忙的系统上,在主线程将
isWaitOver设置为
false
之前,计时器可能会触发
OnTimedEvent
。如果发生这种情况,
isWaitOver
可能在循环中始终显示为false。要防止出现这种情况,请将您的
isWaitOver=false
行置于
aTimer.Enabled=true
之前

更可能的问题是优化器在代码中重新排序。如果单个线程没有注意到差异,则可以执行此操作,但在这样的多线程场景中可能会导致问题。要解决此问题,您可以使
isWaitOver
或输入代码。请看一篇好的评论

一般来说,当易失性和内存障碍产生影响时,代码已经变得复杂和脆弱。内存障碍是非常先进的东西,极易出错,几乎不可能正确测试(例如,行为因您使用的CPU型号而异)。我的建议是切换
isWaitOver
,等待计时器线程发出信号。这还具有防止代码进入占用CPU的旋转循环的额外优势

最后,代码出现句柄泄漏。每次在您周围创建一个新的计时器对象时,您都不会再处理它。您可以在创建一个新的之前处理它,如我所示,或者简单地使用它,而不继续重新创建它

    ManualResetEvent isWaitOver = new ManualResetEvent(false);

    private void Run()
    {
        foreach (DataRow row in ds.Tables[0].Rows)
        {
            string Badge = Database.GetString(row, "Badge");
            if (Badge.Length > 0)
            {
                if (Count < Controller.MaximumBadges)
                {
                    if (processed == 100) // Every 100 downloads, pause for a second
                    {
                        processed = 0;
                        StartTimer();
                        isWaitOver.WaitOne();
                        Controller.PostRecordsDownloadedOf("Badges", Count);
                    }

                    if (Download(Badge, false))
                    {
                        Count++;
                        processed++;
                    }
                }
                else
                    Discarded++;
            }
            TotalCount++;
        }
    }

    private void StartTimer()
    {
        // Create a timer with a one second interval.
        if (aTimer != null) aTimer.Dispose();
        aTimer = new System.Timers.Timer(1000);
        // Hook up the Elapsed event for the timer.
        isWaitOver.Reset();
        aTimer.Elapsed += OnTimedEvent;
        aTimer.AutoReset = true;
        aTimer.Enabled = true;
    }

    private void OnTimedEvent(Object source, System.Timers.ElapsedEventArgs e)
    {
        aTimer.Enabled = false;
        isWaitOver.Set();
    }
ManualResetEvent isWaitOver=新的ManualResetEvent(错误);
私家车
{
foreach(ds.Tables[0].行中的DataRow行)
{
stringbadge=Database.GetString(第行,“Badge”);
如果(徽章长度>0)
{
if(计数<控制器最大负载)
{
如果(processed==100)//每下载100次,暂停一秒钟
{
已处理=0;
StartTimer();
waitover.WaitOne();
控制器。PostRecordsDownloadeof(“徽章”,计数);
}
如果(下载(徽章,假))
{
计数++;
处理++;
}
}
其他的
丢弃的++;
}
TotalCount++;
}
}
私有void StartTimer()
{
//创建一个间隔为1秒的计时器。
如果(aTimer!=null)aTimer.Dispose();
aTimer=新系统计时器计时器(1000);
//连接计时器的已用事件。
isWaitOver.Reset();
aTimer.appeased+=OnTimedEvent;
aTimer.AutoReset=true;
aTimer.Enabled=true;
}
私有void OnTimedEvent(对象源,System.Timers.ElapsedEventArgs e)
{
aTimer.Enabled=false;
isWaitOver.Set();
}

make
isWaitOver
volitile。您不显示声明,但为了使此代码可靠,isWaitOver必须是易变的。是吗?Thread.Sleep是一个循环,你把它修好了!太棒了!谢谢你的详细解释。如果我再次需要这样的解决方案,我会在将来记住这个解决方案。
    ManualResetEvent isWaitOver = new ManualResetEvent(false);

    private void Run()
    {
        foreach (DataRow row in ds.Tables[0].Rows)
        {
            string Badge = Database.GetString(row, "Badge");
            if (Badge.Length > 0)
            {
                if (Count < Controller.MaximumBadges)
                {
                    if (processed == 100) // Every 100 downloads, pause for a second
                    {
                        processed = 0;
                        StartTimer();
                        isWaitOver.WaitOne();
                        Controller.PostRecordsDownloadedOf("Badges", Count);
                    }

                    if (Download(Badge, false))
                    {
                        Count++;
                        processed++;
                    }
                }
                else
                    Discarded++;
            }
            TotalCount++;
        }
    }

    private void StartTimer()
    {
        // Create a timer with a one second interval.
        if (aTimer != null) aTimer.Dispose();
        aTimer = new System.Timers.Timer(1000);
        // Hook up the Elapsed event for the timer.
        isWaitOver.Reset();
        aTimer.Elapsed += OnTimedEvent;
        aTimer.AutoReset = true;
        aTimer.Enabled = true;
    }

    private void OnTimedEvent(Object source, System.Timers.ElapsedEventArgs e)
    {
        aTimer.Enabled = false;
        isWaitOver.Set();
    }