Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/284.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/22.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# 如何使用异步调用检查Web服务是否可用_C#_.net_Web Services - Fatal编程技术网

C# 如何使用异步调用检查Web服务是否可用

C# 如何使用异步调用检查Web服务是否可用,c#,.net,web-services,C#,.net,Web Services,我正在创建一个小的测试应用程序,它将运行几个测试用例来检查系统各个组件的状态。该应用程序被创建为一个.NET Windows窗体应用程序,其中有几个复选框,这些复选框针对通过的每个测试用例进行签入(如果失败,则不选中) 测试之一是检查简单Web服务的可用性。如果webservice可用,则测试用例将成功,否则将失败。我首先尝试通过使用System.Net.HttpWebRequest类来实现这一点,将超时设置为1500毫秒并调用GetResponse。现在,如果webservice不可用,请求应

我正在创建一个小的测试应用程序,它将运行几个测试用例来检查系统各个组件的状态。该应用程序被创建为一个.NET Windows窗体应用程序,其中有几个复选框,这些复选框针对通过的每个测试用例进行签入(如果失败,则不选中)

测试之一是检查简单Web服务的可用性。如果webservice可用,则测试用例将成功,否则将失败。我首先尝试通过使用System.Net.HttpWebRequest类来实现这一点,将超时设置为1500毫秒并调用GetResponse。现在,如果webservice不可用,请求应该超时,测试用例失败。然而,事实证明,超时是在来自webservice的实际响应上设置的。也就是说,超时从与Web服务建立连接时开始计数。如果Web服务根本无法访问,则不会发生超时,因此至少需要30秒,直到testcase失败

为了解决这个问题,有人建议我使用BeginGetResponse进行异步调用,并在请求完成时进行回调。现在,这里也出现了同样的问题,因为如果webservice不可用,则至少需要30秒才能发生回调

现在我想我可以使用System.Timers.Timer,将超时设置为1500毫秒,并在计时器超时时设置一个事件。问题是,计时器将独立于webservice是否可访问而超时,因此事件将独立于webservice是否可访问而触发

现在我没有主意了。我意识到这一定是一个相当容易解决的问题。有人对我如何做到这一点有什么建议吗

我得到了用自己的思路打电话的建议。所以现在我在它自己的线程中执行请求。但是,如果请求没有响应,当我试图将测试状态设置为失败时,应用程序将锁定。但是如果它有响应,我可以将测试状态设置为successed,而不会出现任何问题。此操作的代码:

private void TestWebServiceConnection()
        {
            HttpWebRequest request;
            request = (HttpWebRequest)WebRequest.Create(Url);
            request.BeginGetResponse(new AsyncCallback(FinishWebRequest), null);
            System.Threading.Thread.Sleep(1500);
            SetStatusDelegate d = new SetStatusDelegate(SetTestStatus);
            if (request.HaveResponse)
            {
                if (ConnectionTestCase.InvokeRequired)
                {
                    this.Invoke(d, new object[] { TestStatus.Success});
                }
            }
            else
            {
                if (ConnectionTestCase.InvokeRequired)
                {
                    this.Invoke(d, new object[] { TestStatus.Failure });
                }
            }

        }
        private delegate void SetStatusDelegate(TestStatus t);

        private void SetTestStatus(TestStatus t)
        {
            ConnectionTestCase.Status = t;
        }

ThreadStart ts = new ThreadStart(TestWebServiceConnection);
Thread t = new Thread(ts);
t.Start();

关于我为什么会有这种行为有什么建议吗?塔克斯

为什么不在新线程中执行调用本身?

“计时器将超时,与Web服务是否可访问无关,因此事件将被触发,与Web服务是否可访问无关。”

一旦可以访问Web服务,就可以停止计时器。
如果计时器调用设置为2000毫秒,Web服务调用需要小于2000毫秒完成,则禁用计时器,否则计时器事件将通知Web服务

出错,您还可以考虑使用BuffTeWork对象以更线程安全的方式执行这些调用。它能够执行异步服务并向父窗体/对象报告。然后,您可以将您认为必要的任何时间长度和规则附加到web请求,而无需担心线程异常

嗯。。设置超时的方式真的很奇怪。为什么不使用HttpWebRequest对象的timeout属性?然后用try..catch(TimeoutException)包围HttpWebRequest.GetResponse()。而且它不应该是异步的

此超时正好决定了获得工作连接所需的时间。如果以后要控制最大GetResponse()时间,则应使用MemoryStream读取响应流,它还具有readtimeout属性。就这样

如果仍希望它在单独的线程中运行,请执行以下操作:

Thread testThread = new Thread( () => {
    SetStatusDelegate d = new SetStatusDelegate(SetTestStatus);
    HttpWebRequest request = (HttpWebRequest)WebRequest.Create("yoururl");
    request.Timeout = new TimeSpan( 0, 1, 30 );
    try
    {
        request.GetResponse();
    }
    catch( TimeoutException )
    {
         this.Invoke(d, new object[] { TestStatus.Failure});
    }
    this.Invoke(d, new object[] { TestStatus.Success});
});

或者类似的:)

我试图解决你的问题,但没有完成。也许其他人可以修复其中的bug:

using System;
using System.ComponentModel;
using System.Drawing;
using System.Windows.Forms;
using System.Net;
using System.Threading;

namespace winformapp
{
    public partial class Form1 : Form
    {
        private bool completedInTime = false;
        private HttpWebRequest request = null;
        public delegate void RequestCompletedDelegate(bool completedSuccessfully);
        private static AutoResetEvent resetEvent = new AutoResetEvent(false);
        private System.Threading.Timer timer = null;
        private static readonly object lockOperation = new object();
        public Form1()
        {
            InitializeComponent();
            urlTextBox.Text = "http://twitter.com";
            millisecondsTextBox.Text = "10000";
        }

        private void handleUIUpdateRequest(bool completedSuccessfully)
        {
            resultCheckbox.Checked = completedSuccessfully;
            startTestButton.Enabled = true;
            completedInTime = false;
        }

        private void button1_Click(object sender, EventArgs e)
        {
            startTestButton.Enabled = false;
            try
            {
                TestWebServiceConnection(urlTextBox.Text,
                    Convert.ToInt32(millisecondsTextBox.Text));
                resetEvent.WaitOne();
                resultCheckbox.BeginInvoke(new RequestCompletedDelegate(handleUIUpdateRequest), completedInTime);
                timer.Change(Timeout.Infinite, Timeout.Infinite);
            }
            catch (Exception ex)
            {

            }
        }
        private void TestWebServiceConnection(string url, int timeoutMilliseconds)
        {
            request = (HttpWebRequest)WebRequest.Create(url);
            request.BeginGetResponse(new AsyncCallback(FinishWebRequest), null);
            timer = new System.Threading.Timer(new TimerCallback(abortRequest), null, timeoutMilliseconds, Timeout.Infinite);
        }
        private void FinishWebRequest(IAsyncResult iar)
        {
                lock (lockOperation)
                {
                    completedInTime = true;
                    resetEvent.Set();
                }

                /*
                if (timer != null)
                {
                    timer.Dispose();
                    try
                    {
                        if (request != null)
                        {
                            request.Abort();
                        }
                    }
                    catch { }
                }
                timer = null;
                request = null;

            }
                 * */
        }
        private void abortRequest(object state)
        {
            lock (lockOperation)
            {
                resetEvent.Set();
            }
            try
            {
                Thread.CurrentThread.Abort();
            }
            catch {}
            /*
            lock (lockOperation)
            {
                if (!completedInTime)
                {
                    resetEvent.Set();
                }
            }

            if (completedInTime == false)
            {
                lock (lockOperation)
                {
                    completedInTime = false;
                }
                try
                {
                    if (request != null)
                    {
                        request.Abort();
                    }
                }
                catch { }
                try
                {
                    if (timer != null)
                    {
                        timer.Dispose();
                    }
                }
                catch { }
                finally
                {
                    resetEvent.Set();
                }

                request = null;
                timer = null;

            }
             * */
        }
    }
}

我试着听从你的建议。所以我把电话放在了它自己的线程中。当然,当我试图设置表单中复选框的状态时,我会得到异常(跨线程调用)。为了解决这个问题,我试着让它线程安全。但是,如果请求没有响应,当我试图将测试状态设置为失败时,应用程序将锁定。我在问题中发布了上面的代码。我听从了你的建议,在一个单独的线程上打了电话。调用thread.start()后,我让应用程序休眠大约一秒钟。如果未收到响应,则测试默认为失败。谢谢你的帮助!