简体   繁体   English

在指定时间后终止功能

[英]Terminating a function after a specified time

Im working on an EConnect integration Windows form app in C#. 我正在用C#开发EConnect集成Windows窗体应用程序。 Im having a lot of trouble testing my connection string. 我在测试我的连接字符串时遇到很多麻烦。 Basically I give the user the option to change the connection string so I want to be able to test it. 基本上,我为用户提供了更改连接字符串的选项,因此我希望能够对其进行测试。 As far as I know EConnect doesnt have any built in functions that test the connection so I'm writing a pretty crude function to do it myself. 据我所知,EConnect没有任何可测试连接的内置函数,因此我自己编写了一个很简单的函数。 Just for everyones information the connection string consists of a server name that the GP databases are located on and a database name. 仅向所有人提供信息,连接字符串由GP数据库所在的服务器名称和数据库名称组成。

The particulars of the actual test function I dont think are that important but the main issue is within that function I call an eConnect method called getEntity, this method uses the connection string and if the connection string is right it will pull information. 我认为实际测试功能的细节并不重要,但是主要问题在于该功能内,我调用了一个名为getEntity的eConnect方法,该方法使用连接字符串,如果连接字符串正确,它将提取信息。 If the database name is wrong the getEntity method will return an eConnect exception which is easy enough to catch, however if the server name is wrong the getEntity method will just spin and my app gets stuck. 如果数据库名称错误,则getEntity方法将返回一个eConnect异常,该异常很容易捕获,但是,如果服务器名称错误,则getEntity方法将旋转并且我的应用程序卡住。

Im trying to write something where I can possibly run my test function asynchronously and simultaneously check for a timeout or the econnect exception. 我试图写一些我可以异步运行我的测试功能,同时检查超时或econnect异常的东西。 This is where I get stuck, I cant for the life of me get it to work. 这就是我被困住的地方,我无法终生获得工作。 Here is the first thing I tried (this is in my TestConnection method): 这是我尝试过的第一件事(这在我的TestConnection方法中):

task = Task.Factory.StartNew(() => requester.GetEntity(GPCongfigSettings.GPConnectionString, myXmlDocument.OuterXml), token);

try
{
    if (!task.Wait(timeOut, token))
    {
        Console.WriteLine("The server name is incorrect - task timed out");
        return false;
    }
}
catch (ThreadInterruptedException)
{
return false;
}
catch (AggregateException ae)
{
    ae.Handle((x) =>
    {
        if (x is eConnectException) // This we know how to handle.
        {
            Console.WriteLine("Incorrect Database Name! -- " + x.Message);
            return false;
        }
        return false; // Let anything else stop the application.
    });

}

This would catch the cases where the server was wrong and if my econnect method would just time out. 如果我的econnect方法超时,这将捕获服务器错误的情况。 But it never caught the eConnect exception, Visual Studio would break the app and tell me I had an unhandled exception. 但是它从未捕获到eConnect异常,Visual Studio会中断应用程序并告诉我我有未处理的异常。

Here is what Im trying now, this is the full class I have for my form. 这是我现在正在尝试的内容,这是我准备的完整课程。 Here I'm trying to use IAsyncResult and using a WaitHandle to check to see if the function completes or times out. 在这里,我尝试使用IAsyncResult并使用WaitHandle来检查函数是否完成或超时。 This seems to work sometimes, it works for a correct string and for when the database is wrong, and sometimes it works for when the server is wrong, but once I test for a wrong server name it doesnt work correctly for anything else anymore. 这似乎有时起作用,它适用于正确的字符串,适用于数据库错误的情况,有时适用于服务器错误的情况,但是一旦我测试了错误的服务器名称,它就无法再用于其他任何功能。 Is there something I'm missing or is there a better way to run the getentity method in TestGPConnection and check to see if it hasnt completed after a certain time period and if it hasnt kill that method and have the user reenter a server name? 是否有我缺少的东西,或者有更好的方法在TestGPConnection中运行getentity方法,并检查它是否在特定时间段后还没有完成,是否还没有杀死该方法并让用户重新输入服务器名称?

public partial class UpdateGPConnection : Form
{
    Task task;
    AsyncCallback cb;
    public delegate string startProcessToCall();
    startProcessToCall sp2c;       

    public UpdateGPConnection()
    {
        InitializeComponent();
        this.txtDatasourceName.Text = ConfigurationManager.AppSettings.Get("GPDataServer");
        this.txtDatabaseName.Text = ConfigurationManager.AppSettings.Get("GPDatabase");                   

        cb = new AsyncCallback(startProcessCallback);
        sp2c = new startProcessToCall(TestGPConnection);
    }

    public void startProcessCallback(IAsyncResult iar)
    {
        startProcessToCall mc = (startProcessToCall)iar.AsyncState;
        bool result = mc.EndInvoke(iar);
        Console.WriteLine("Function value = {0}", result);
    }

    private void btnUpdate_Click(object sender, EventArgs e)
    {
        var config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
        config.AppSettings.Settings["GPDataServer"].Value = txtDatasourceName.Text.ToUpper();
        config.AppSettings.Settings["GPDatabase"].Value = txtDatabaseName.Text.ToUpper();
        config.Save(ConfigurationSaveMode.Modified);

        ConfigurationManager.RefreshSection("appSettings");

        GPCongfigSettings.GPConnectionString = @"data source=" + txtDatasourceName.Text.ToUpper() + ";initial catalog=" + txtDatabaseName.Text.ToUpper() + ";integrated security=SSPI;persist security info=False;packet size=4096";

        IAsyncResult asyncResult = null;
        asyncResult = sp2c.BeginInvoke(cb, null);
        timer1.Enabled = true;

        Thread.Sleep(0);

        bool test = asyncResult.AsyncWaitHandle.WaitOne(15000);

        if (test)
        {
            try
            {
                string testResult = sp2c.EndInvoke(asyncResult);
            }
            catch (Exception exc)
            {
                Console.WriteLine(exc.Message);
            }
        }



        bool result = asyncResult.IsCompleted;

        asyncResult.AsyncWaitHandle.Close();

        this.Close();
    }



    public string TestGPConnection()
    {

        eConnectMethods requester = new eConnectMethods();
        try
        {                

            // Create an eConnect document type object
            eConnectType myEConnectType = new eConnectType();

            // Create a RQeConnectOutType schema object
            RQeConnectOutType myReqType = new RQeConnectOutType();

            // Create an eConnectOut XML node object
            eConnectOut myeConnectOut = new eConnectOut();

            // Populate the eConnectOut XML node elements
            myeConnectOut.ACTION = 1;
            myeConnectOut.DOCTYPE = "GL_Accounts";
            myeConnectOut.OUTPUTTYPE = 2;
            myeConnectOut.FORLIST = 1;
            myeConnectOut.WhereClause = "(ACTNUMST = '99-9999-99-999')";

            // Add the eConnectOut XML node object to the RQeConnectOutType schema object
            myReqType.eConnectOut = myeConnectOut;

            // Add the RQeConnectOutType schema object to the eConnect document object
            RQeConnectOutType[] myReqOutType = { myReqType };
            myEConnectType.RQeConnectOutType = myReqOutType;

            // Serialize the eConnect document object to a memory stream
            MemoryStream myMemStream = new MemoryStream();
            XmlSerializer mySerializer = new XmlSerializer(myEConnectType.GetType());
            mySerializer.Serialize(myMemStream, myEConnectType);
            myMemStream.Position = 0;

            // Load the serialized eConnect document object into an XML document object
            XmlTextReader xmlreader = new XmlTextReader(myMemStream);
            XmlDocument myXmlDocument = new XmlDocument();
            myXmlDocument.Load(xmlreader);

            string reqDoc = requester.GetEntity(GPCongfigSettings.GPConnectionString, myXmlDocument.OuterXml);

            return "Correct Connection";


        }
        catch (eConnectException exc)
        {
            Console.WriteLine(exc.Message);
            return "eConnect Excpetion";
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
            return "Excpetion";
        }
    }

    private void btnExit_Click(object sender, EventArgs e)
    {
        this.Close();
    }


}

You are not handling the eConnectException . 您没有处理eConnectException You are showing a message in the Console and then essentially rethrowing the exception by returning false . 您正在Console中显示一条消息,然后实质上通过返回false引发异常。

If you do handle an exception then you should return true to avoid rethrowing it: 如果您确实处理了异常,则应返回true以避免再次抛出该异常:

catch (AggregateException ae)
{
    ae.Handle((x) =>
    {
        if (x is eConnectException) // This we know how to handle.
        {
            Console.WriteLine("Incorrect Database Name! -- " + x.Message);
        }

        return x is eConnectException; //rethrow anything that is not an eConnectException
    });
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM