由于waitOne,C#格式变慢了

时间:2014-04-18 09:55:16

标签: c# json multithreading forms waitone

我遇到了一些问题,尝试使用JSON将设备代码编写为设备。

我的设备到设备运行良好,我正在使用它通过自制的D2D服务器将JSON发送到其他设备。 所以我的一个客户端正在向另一个名为“server”的客户端发送请求,该服务器正在做一些事情(在Asterisk服务器上做一些请求),一切都很好。

但是我遇到了一个问题: 当我的客户端向我的服务器发送请求时,我正在等待来自服务器的回答,并在autoResetEvent上使用waitOne。根据请求,我的表单将显示弹出窗口。 但是我的表单显示弹出窗口很慢,我认为这是由于那些waitOne,我可以在不到3秒的时间内发送10个请求,所以我认为我的表格因这些原因而变慢。

基本上,我正在使用一个在套接字上读取数据的线程,当我的数据完成时(整个Json被检索),我发送一个事件,然后我必须释放读取线程,所以我'我做了一个“BeginInvoke”,所以我的表单将处理事件:

 _sync.BeginInvoke(ChannelChange, new Object[] {this, ec});

显示弹出窗口后,我的表单正在处理多个其他事件,它正在向服务器发出一些请求(因此在多个请求期间线程停止)。

所以我猜,这就是为什么我的弹出窗口显示得很慢。 所以我的问题是如何避免这种减速?

简历:

MyForm正在使用客户端,该客户端包含一些方法,如“retrieveChannelById”。当我的阅读线程正在检索一个完整的Json时,它正在抛出一个调用我的表单的事件(如果我没有用我的表单调用该事件,我的阅读线程将被停止并且它是最糟糕的)我的表单正在执行一些客户端方法,如“retrieveChannelById”将线程设置为暂停一段时间(通常不到1秒,但它正在快速地执行大量请求)。

所以我想知道,如何在不暂停表单线程的情况下指定一个线程来执行这些方法?

但是,当我正在处理一个事件时,我正在做

Channel chan = Client.GetChannelByChanID(e.ChannelId);

我真的不知道如何处理这种形式的减速,我是否必须在另一个线程中执行这些方法? (它不会改变任何我想的,因为我的表单必须等待另一个线程才能使通道正确?)。我需要一个解决方案,所以我的表单线程没有设置在WaitOne上,我认为这是我的问题。

真的很难解释,实际上......

这是我的方法retrieveChannelById:

   SendD2DMessage("*", "server", "{\"classname\":\"GetChannelByChanID\",\"chanID\":\"" + chanID + "\"}");
        waitingData = "reponseGetChannelByID";           
        if (this._messageRecieved.WaitOne(5000))
        {

            try
            { 
                if (dataRecieved == "null")
                {
                    Console.WriteLine("But data null");
                    return null;
                }
                else
                {
                    Channel chan = JsonConvert.DeserializeObject<Channel>(dataRecieved);
                    Console.WriteLine("Channel received : " + chan.Extension);
                    return chan;
                }
            }
            catch (Exception ex)
            {
                SynsipClientLog.Log("Error while deserializing Channel Object in GetChannelByID Method :" + ex.Message);
                return null;
            }
        }
        else
        {
            waitingData = "";
            Console.WriteLine("Channel NOT RECEIVED");
            SynsipClientLog.Log("No response from D2DConsole in GetChannelByChanId method");
            return null;
        }

这是ChannelChange代码,这段代码是我的主要形式。

  void SynsipCli_ChannelChange(object sender, SynsipRemoteChannelChangeEventsArgs e)
    {
        try
        {
            //Console.WriteLine("test ChannelChange");
            Channel chan = SynsipCli.GetChannelByChanID(e.ChannelId);
            Channel linkedChan = null;
            if (chan != null && chan.LinkedChannelID.Length>1)
            {
                linkedChan = SynsipCli.GetChannelByChanID(chan.LinkedChannelID);
            }

            // alertes pour les trunck
            if (e.Channelcategory == ChannelCategory.Trunck && !MenuDoNotDisplay.Checked)
            {
                bool isGeneralNumber = false;

                if (chan != null)
                {
                    foreach (string str in SynsipCli.AstParameters.GeneralNumbers)
                    {
                        if (chan.CallerIDNum.Contains(str) || chan.LinkedCallerID.Contains(str) || chan.DNIS.Contains(str) || chan.Extension.Contains(str))
                            isGeneralNumber = true;
                    }

                    if (chan.State != ChannelState.Down && chan.State != ChannelState.Hangup && chan.State != ChannelState.Unknow && (chan.LinkedCallerID == Extension || chan.CallerIDNum == Extension || isGeneralNumber))
                    {

                        LaunchAlert(chan);
                    }

                }
            }
            else if (linkedChan != null && linkedChan.ChannelCategory == ChannelCategory.Trunck)
            {
                bool isGeneralNumber = false;

                if (linkedChan != null)
                {
                    foreach (string str in SynsipCli.AstParameters.GeneralNumbers)
                    {
                        if (linkedChan.CallerIDNum.Contains(str) || linkedChan.LinkedCallerID.Contains(str) || linkedChan.DNIS.Contains(str))
                            isGeneralNumber = true;
                    }

                    if (linkedChan.State != ChannelState.Down && linkedChan.State != ChannelState.Hangup && linkedChan.State != ChannelState.Unknow && (linkedChan.LinkedCallerID == Extension || linkedChan.CallerIDNum == Extension || isGeneralNumber))
                    {
                        LaunchAlert(linkedChan);

                        //LaunchAlert(tchan);

                    }

                }

            }
            if (((chan != null && (chan.CallerIDNum == txtExtention.Text || chan.LinkedCallerID == txtExtention.Text)) || e.Extension == txtExtention.Text) && !MenuDoNotDisplay.Checked) // alertes pour le local
            {
                string ext = SynsipCommunicator.Properties.Settings.Default.Extention;

                Extension exten = SynsipCli.GetExtension(ext);

                foreach (Channel tchan in exten.Channels)
                {
                    if (tchan != null && tchan.CalllType == CallType.Internal)
                    {
                        LaunchAlert(tchan);


                    }
                }
            }

            // suppression des alerts qui ne doivent plus exister
            for (int i = 0; i < Alerts.Count; i++)
            {
                Channel tchan = SynsipCli.GetChannelByChanID(Alerts[i].chanId);
                if (tchan == null)
                    Alerts[i].Close();
                else if (tchan.State == ChannelState.Down || tchan.State == ChannelState.Hangup || tchan.State == ChannelState.Unknow)
                    Alerts[i].Close();
            }
        }
        catch (Exception exe)
        {
            //Console.WriteLine("ERREUR CHANNEL CHANGE " + exe.Message);
        }

    }

LaunchAlert方法只是检查我的Channel对象中的一些东西,创建一个框架然后显示框架:

 if (!MenuDoNotDisplay.Checked)
            {
                ShowWindow(frma.Handle, 4); //Pour éviter de prendre le focus
                SetWindowPos(frma.Handle, -1, frma.Location.X, frma.Location.Y, frma.Width, frma.Height, 0x0010);
            }

1 个答案:

答案 0 :(得分:0)

不要在UI线程上执行任何阻塞等待(如event.WaitOne())。这将导致您正在描述的死行为,因为UI在此期间无法自行更新。

相反,你应该异步工作: 只在UI线程上启动操作然后立即返回。操作完成后再切换回UI线程(例如,使用BeginInvoke),评估结果以及是否仍需要操作,并根据操作结果更新UI。

如果你想像你的5s一样超时,那么异步启动发送操作并在UI中并行异步启动一个计时器。两者都应该在UI线程中完成。然后查看您的计时器是先完成还是先收到操作结果并处理该情况。

您也可以在C#TPL Task对象中包装Send操作,或使用C#async / await功能使整个代码更具可读性和可组合性。