C# Can';除非我添加了一个线程,否则我不能将Task.Result返回字符串

C# Can';除非我添加了一个线程,否则我不能将Task.Result返回字符串,c#,task-parallel-library,async-await,C#,Task Parallel Library,Async Await,第一次在这里问问题,我会尽量具体一些 我在工作中使用基于网络的Api,我很难让任务返回结果 我有一个交易类,它有一个Buy方法和一个GetOrderNumber方法。在我的MainForm上,我使用一个任务来执行交易,然后检索与该交易关联的ordernumber NewTrade Test = new NewTrade(); Task<string> tmp = Task.Factory.StartNew(() => Test.Buy("JPM.NY", 100, 59.50

第一次在这里问问题,我会尽量具体一些

我在工作中使用基于网络的Api,我很难让任务返回结果

我有一个交易类,它有一个Buy方法和一个GetOrderNumber方法。在我的MainForm上,我使用一个任务来执行交易,然后检索与该交易关联的ordernumber

NewTrade Test = new NewTrade();

Task<string> tmp = Task.Factory.StartNew(() => Test.Buy("JPM.NY", 100, 59.50));
string reqid = tmp.Result;

Task<string> tmp2 = Task.Factory.StartNew(() => Test.GetOrderNumber(reqid));

Console.WriteLine(tmp2.Result);
NewTrade测试=新的NewTrade();
Task tmp=Task.Factory.StartNew(()=>Test.Buy(“JPM.NY”,10059.50));
字符串REQUID=tmp.Result;
Task tmp2=Task.Factory.StartNew(()=>Test.GetOrderNumber(reqid));
控制台写入线(tmp2.Result);
第一个任务返回一个REQID号。第二个任务使用REQID号并返回所下交易的实际订单号

我遇到的问题是,我从第一个任务中获取了ReqID号,但在第二个任务中返回空白

但是,如果我在第一个任务和第二个任务之间添加一个Thread.sleep(),我就会得到订单号

我使用的是任务,因为最终会有数百个订单被下订单,关键是要有每个订单的订单号

class NewTrade
{ 
   public string Buy(string stkName, int stkShares, double limitPrice)
    {
        try
        {
            using (MyWebClient client = new MyWebClient())
            {

                Stream data = client.OpenRead("http://localhost:8080/ExecuteOrder?symbol=" + stkName + "&limitprice=" + limitPrice + "&ordername=ARCA%20Buy%20ARCX%20Limit%20DAY&shares=" + stkShares);
                StreamReader reader = new StreamReader(data);
                string s = reader.ReadToEnd();
                s = getBetween(s, "<Content>", "</Content>"); //this is a util function to parse the result
                // MessageBox.Show(s.ToString());
                data.Close();
                reader.Close();

                return s;
            }
        }
        catch (WebException e)
        {
            Console.WriteLine(e.Message);
            Console.WriteLine(e.StackTrace);
            return "Nothing";
        }
    }

    public string GetOrderNumber(string id)
    {
        string s = "";

        using (MyWebClient client = new MyWebClient())
        {
            try
            {
                WebRequest request = WebRequest.Create("http://localhost:8080/GetOrderNumber?requestid=" + id);
                WebResponse response = request.GetResponse();
                var reader = new StreamReader(response.GetResponseStream());

                s = reader.ReadToEnd();
                Console.WriteLine(s);
                return s;
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.ToString());
                return "";
            }
        }
    }
}
class-NewTrade
{ 
公共字符串购买(字符串stkName、int stkShares、双倍限价)
{
尝试
{
使用(MyWebClient=new MyWebClient())
{
流数据=client.OpenRead(“http://localhost:8080/ExecuteOrder?symbol=“+stkName+”&limitprice=“+limitprice+”&ordername=ARCA%20Buy%20ARCX%20Limit%20DAY&shares=“+stkShares”);
StreamReader=新的StreamReader(数据);
字符串s=reader.ReadToEnd();
s=getBetween(s,“,”);//这是一个用于分析结果的util函数
//Show(s.ToString());
data.Close();
reader.Close();
返回s;
}
}
捕获(WebE例外)
{
控制台写入线(e.Message);
控制台写入线(如StackTrace);
返回“无”;
}
}
公共字符串GetOrderNumber(字符串id)
{
字符串s=“”;
使用(MyWebClient=new MyWebClient())
{
尝试
{
WebRequest=WebRequest.Create(“http://localhost:8080/GetOrderNumber?requestid=“+id);
WebResponse=request.GetResponse();
var reader=newstreamreader(response.GetResponseStream());
s=reader.ReadToEnd();
控制台。写入线(s);
返回s;
}
捕获(例外情况除外)
{
Console.WriteLine(例如ToString());
返回“”;
}
}
}
}

使用
任务
s可以使应用程序更具可伸缩性,因为您可以在异步任务进行期间使线程处理其他任务。这就是说,使用
Task.Run
Task.Factory.StartNew
在后台执行IO任务会破坏这一目的。您需要通过调用正在使用的IO构造的
async
API,使您的方法真正实现
async
。尝试将代码更改为以下内容:

public Task<string> MakeTradeAsync()
{
    NewTrade Test = new NewTrade();

    string reqid = await Test.Buy("JPM.NY", 100, 59.50);

    string orderNumber = await Test.GetOrderNumber(reqid);

    Console.WriteLine(orderNumber);

    return orderNumber;
}

@然后,让它显示出来。还可以使用@not-让与您交谈的用户注意到您的评论。请对您的问题进行分析,我们只需复制代码并亲自运行它就可以了(您能在没有网络客户端调用的情况下复制问题吗?@ScottChamberlain就可以了。1)为什么您要使用任务,然后立即执行
任务。结果
,你只是在等待任务加速,从而放慢了速度。如果直接运行代码而不需要任何任务,您将获得更好的性能。2) 如果你假装它,只是硬编码一个字符串响应,会发生什么呢?尽量使问题变得简单,但仍要重新创建问题。我认为这应该使用
async
wait
调用。您正在
GetOrderNumber
中吞咽异常。您是否尝试过在
catch
块中设置断点以查看是否出现断点?我尝试过使用建议的更改,但仍然遇到空白返回的问题。如果我在开始时在OrderNumber方法中执行Thread.Sleep(50),一切正常……我不知道为什么……服务器上可能发生了一些异步操作,因此执行睡眠会使它在下次调用时及时完成。我会看看当你调用
client.OpenRead
与其他交易者交谈时,服务器端会发生什么,他们能够在交易执行后2毫秒内从同一服务器上取款。不过他在使用python…也许他们的查询不同?如果可以的话,试着使用相同的url,这可能会缩小范围。我看了一下,我们都有一个标准的查询。我检查了一下是否输入了错。但是如果我加上延迟,就没什么效果了。这几乎就像在Web服务器的第一次httprequest之后,它只是挂起一点,然后一旦退出,我就可以执行OrderNumber方法并接收OrderNumber。。。
 public async Task<string> Buy(string stkName, int stkShares, double limitPrice)
 {
    try
    {
        using (MyWebClient client = new MyWebClient())
        {
            // use async API here to get the data, assuming existance of OpenReadAsync
            Stream data = await client.OpenReadAsync("http://localhost:8080/ExecuteOrder?symbol=" + stkName + "&limitprice=" + limitPrice + "&ordername=ARCA%20Buy%20ARCX%20Limit%20DAY&shares=" + stkShares);
            StreamReader reader = new StreamReader(data);
            string s = reader.ReadToEnd();
            s = getBetween(s, "<Content>", "</Content>"); //this is a util function to parse the result
            // MessageBox.Show(s.ToString());
            data.Close();
            reader.Close();

            return s;
        }
    }
    catch (WebException e)
    {
        Console.WriteLine(e.Message);
        Console.WriteLine(e.StackTrace);
        return "Nothing";
    }
}

public async Task<string> GetOrderNumber(string id)
{
    string s = "";

    using (MyWebClient client = new MyWebClient())
    {
        try
        {
            WebRequest request = WebRequest.Create("http://localhost:8080/GetOrderNumber?requestid=" + id);
            WebResponse response = await request.GetResponseAsync();
            var reader = new StreamReader(response.GetResponseStream());

            s = await reader.ReadToEndAsync();
            Console.WriteLine(s);
            return s;
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.ToString());
            return "";
        }
    }
}