c#使用多线程发送HTTP请求的问题,高手进!~~~

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了c#使用多线程发送HTTP请求的问题,高手进!~~~相关的知识,希望对你有一定的参考价值。

用C#做一个WinForm程序,向设置好的IP和端口发送请求,并接收响应的数据。已经实现,但是速度太慢,有什么办法能加快速度。
已使用了多线程,还是慢,发送前两个很快,之后就要等很长时间,要等前面的数据反回之后,才能够再发出去,这是怎么回事?怎么解决?
public void SendData()
for (int i = 0; i < listView1.Items.Count; i++)
phone = listView1.Items[i].SubItems[0].Text;
Start(phone);


public void Start(object phone)

....

不行啊,用多线程不行,改成异步发送和接收也不行,发两个就要等待,还有其它办法没有??

MSDN:
.NET Framework 类库
Thread 类
创建并控制线程,设置其优先级并获取其状态。

命名空间:System.Threading
程序集:mscorlib(在 mscorlib.dll 中)
备注
一个进程可以创建一个或多个线程以执行与该进程关联的部分程序代码。使用 ThreadStart 委托或 ParameterizedThreadStart 委托指定由线程执行的程序代码。使用 ParameterizedThreadStart 委托可以将数据传递到线程过程。

在线程存在期间,它总是处于由 ThreadState 定义的一个或多个状态中。可以为线程请求由 ThreadPriority 定义的调度优先级,但不能保证操作系统会接受该优先级。

GetHashCode 提供托管线程的标识。在线程的生存期内,无论获取该值的应用程序域如何,它都不会和任何来自其他线程的值冲突。

注意
操作系统 ThreadId 和托管线程没有固定关系,这是因为非托管宿主能控制托管与非托管线程之间的关系。特别是,复杂的宿主可以使用 CLR Hosting API 针对相同的操作系统线程调度很多托管线程,或者在不同的操作系统线程之间移动托管线程。

下面的代码示例说明简单的线程处理功能。
using System;
using System.Threading;

// Simple threading scenario: Start a static method running
// on a second thread.
public class ThreadExample
// The ThreadProc method is called when the thread starts.
// It loops ten times, writing to the console and yielding
// the rest of its time slice each time, and then ends.
public static void ThreadProc()
for (int i = 0; i < 10; i++)
Console.WriteLine("ThreadProc: ", i);
// Yield the rest of the time slice.
Thread.Sleep(0);



public static void Main()
Console.WriteLine("Main thread: Start a second thread.");
// The constructor for the Thread class requires a ThreadStart
// delegate that represents the method to be executed on the
// thread. C# simplifies the creation of this delegate.
Thread t = new Thread(new ThreadStart(ThreadProc));
// Start ThreadProc. On a uniprocessor, the thread does not get
// any processor time until the main thread yields. Uncomment
// the Thread.Sleep that follows t.Start() to see the difference.
t.Start();
//Thread.Sleep(0);

for (int i = 0; i < 4; i++)
Console.WriteLine("Main thread: Do some work.");
Thread.Sleep(0);


Console.WriteLine("Main thread: Call Join(), to wait until ThreadProc ends.");
t.Join();
Console.WriteLine("Main thread: ThreadProc.Join has returned. Press Enter to end program.");
Console.ReadLine();



此代码产生的输出类似如下内容:
Main thread: Start a second thread.
Main thread: Do some work.
ThreadProc: 0
Main thread: Do some work.
ThreadProc: 1
Main thread: Do some work.
ThreadProc: 2
Main thread: Do some work.
ThreadProc: 3
Main thread: Call Join(), to wait until ThreadProc ends.
ThreadProc: 4
ThreadProc: 5
ThreadProc: 6
ThreadProc: 7
ThreadProc: 8
ThreadProc: 9
Main thread: ThreadProc.Join has returned. Press Enter to end program.
参考技术A 能贴出点代码来吗?
在st.Write(buffer, 0, buffer.Length);后面加上st.Flush();试试。追问

还是不行,发完第二个要等十几秒。。。。

参考技术B HttpWebResponse?
要是的话每次请求完了需要关闭(这个两个都关闭就好了):
httpReq.Abort(); //HttpWebRequest
httpRes.Close(); //HttpWebResponse
参考技术C 你这并不是多线程:
public void SendData()
for (int i = 0; i < listView1.Items.Count; i++)
phone = listView1.Items[i].SubItems[0].Text;
ThreadPool.QueueUserWorkItem(Start, phone);


public void Start(object phone)

byte[] buffer = Encoding.ASCII.GetBytes(GetXML(phone.ToString()));
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(txtUrl.Text);
request.ContentLength = buffer.Length;
request.Method = "POST";
request.ContentType = "application/x-www-form-urlencoded";
Stream st = request.GetRequestStream();
st.Write(buffer, 0, buffer.Length);
this.Receive(request);
参考技术D 没用过呵呵不好意思

如何通过 HTTP 使用 Java(或 C#)中的摘要身份验证 HTTP 发送 SOAP 请求?

【中文标题】如何通过 HTTP 使用 Java(或 C#)中的摘要身份验证 HTTP 发送 SOAP 请求?【英文标题】:How to send SOAP request over HTTP use digest authentication HTTP in Java (or C#)? 【发布时间】:2015-03-05 10:31:01 【问题描述】:

我有网址为http://192.168.0.10/services/abc?wsdl的网络服务 此 Web 服务器使用摘要身份验证,用户名为 admin,密码为 admin 我想将请求跟随发送到此服务器

SOAP 请求 XML 是 SOAP_RQ.XML

 <soapenv:Envelope
    xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:log="LogsGet" xmlns:mal="MalteseGlobal" xmlns:job="JobGlobal">
         <soapenv:Body>
             <log:LogsGetReq Cmd="Start" OpV="01.00.00" Sev="Info to critical"/>
          </soapenv:Body>
</soapenv:Envelope>     

我的代码:

 private static SOAPMessage createSOAPRequest(String username, String password) throws Exception 
        MessageFactory messageFactory = MessageFactory.newInstance();
        SOAPMessage soapMessage = messageFactory.createMessage();
        SOAPPart soapPart = soapMessage.getSOAPPart();
        // SOAP Envelope
        SOAPEnvelope envelope = soapPart.getEnvelope();
        envelope.addNamespaceDeclaration("log", "LogsGet");
        envelope.addNamespaceDeclaration("mal", "MalteseGlobal");
        envelope.addNamespaceDeclaration("job", "JobGlobal");
        // SOAP Body
        SOAPBody soapBody = envelope.getBody();
        SOAPElement soapBodyElem = soapBody.addChildElement("LogsGetReq", "log");
        QName Cmd = new QName("Cmd");
        QName OpV = new QName("OpV");
        QName Sev = new QName("Sev");
        soapBodyElem.addAttribute(Cmd, "Start");
        soapBodyElem.addAttribute(OpV, "01.00.00");
        soapBodyElem.addAttribute(Sev, "Info to critical");
        //SOAP Header
        MimeHeaders hd = soapMessage.getMimeHeaders();
        hd.addHeader("UsernameToken", username);
        hd.addHeader("PasswordText", password);

        soapMessage.saveChanges();       
        return soapMessage;
    

public void sendSoapRequest(String url, String username, String password) 
        try 
            // Create SOAP Connection
            SOAPConnectionFactory soapConnectionFactory = SOAPConnectionFactory.newInstance();
            SOAPConnection soapConnection = soapConnectionFactory.createConnection();

            // Send SOAP Message to SOAP Server         
            SOAPMessage soapResponse = soapConnection.call(createSOAPRequest(username, password, txtArea), url);
            // Process the SOAP Response               
            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            soapResponse.writeTo(bos);
            System.out.println();  
            soapConnection.close();

         catch (Exception e) 
            System.out.println("Error occurred while sending SOAP Request to Server");              
            e.printStackTrace();
        
    

当我发送请求时,我收到以下消息: 错误响应:(需要 401 授权)

如果我发送请求,请使用 curl 工具 (http://curl.haxx.se/download/curl-7.41.0.zip) 命令行: curl.exe -X POST http://192.168.0.10/services/Maltese -H "Content-Type: text/xml; charset=utf-8" -H "SOAPAction:LogsGet" --digest -u admin:admin -d @SOAP_RQ.xml -v 我收到消息回复正常。

任何人都可以帮助我,如何使用 JAVA(或 C#)通过 HTTP 发送 SOAP 请求?

谢谢

【问题讨论】:

【参考方案1】:
// I used Apache HttpClient.
// For URL, you need to find end point URL.
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.HttpResponse;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.util.EntityUtils;

import java.io.PrintWriter;
import java.io.StringWriter;

// Input parameter
String username = "";
String password = "";
String url = "";

// Variables 
int responseCode = 0;
String errorMessage = "";
String responseContent = "";
String content = ""

HttpResponse response;

try

    content = 
        "<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:log=\"LogsGet\" xmlns:mal=\"MalteseGlobal\" xmlns:job=\"JobGlobal\">" + 
        "\n  <soapenv:Body>" +
        "\n    <log:LogsGetReq Cmd=\"Start\" OpV=\"01.00.00\" Sev=\"Info to critical\"/>" + 
        "\n  </soapenv:Body>" +
        "\n</soapenv:Envelope>";

    // Create the POST object and add the parameters
    HttpPost httpPost = new HttpPost(url);
    httpPost.addHeader("Content-Type", "text/xml; charset=utf-8");

    // Enable preemptive authentication within HttpClient so that HttpClient will 
    // send the basic authentications reponse before the server gives an unauthorized reponse. 
    String host = httpPost.getURI().getHost();
    int port = httpPost.getURI().getPort();   
    AuthScope authScope = new AuthScope(host, port);
    DefaultHttpClient httpClient = new DefaultHttpClient();
    UsernamePasswordCredentials credentials = new     UsernamePasswordCredentials(username, password);
    httpClient.getCredentialsProvider().setCredentials(authScope, credentials);   

    StringEntity input = new StringEntity(content);
    input.setContentType("application/json");
    httpPost.setEntity(input);   
    response = httpClient.execute(httpPost);

    if (response != null && response.getStatusLine() != null)
    
        responseCode = response.getStatusLine().getStatusCode();
        responseContent = EntityUtils.toString(response.getEntity());
    

    System.out.println("\n\n-----------------------------");
    System.out.println("\nResponse code: " + responseCode);
    System.out.println("\nResponse content: " + responseContent);

catch (Exception e)

    errorMessage  += "\nUnexpected Exception: " + e.getMessage();
    StringWriter sWriter = new StringWriter();
    PrintWriter pWriter = new PrintWriter(sWriter, true);
    e.printStackTrace(pWriter);
    errorMessage += "\n" + sWriter.getBuffer().toString();

    errorMessage += "\n------------Error Detail------------";
    errorMessage += "\n" + e;
    errorMessage += "\n" + e.getMessage();
    errorMessage += "\n" + e.getLocalizedMessage();
    errorMessage += "\n" + e.getCause();
    errorMessage += "\n" + Arrays.toString(e.getStackTrace());
    errorMessage += "\n" + e.printStackTrace();
    errorMessage += "\n------------------------------------";

finally

    if(response)
    
        EntityUtils.consume(response.getEntity());    
    


if(errorMessage != "")

    System.out.println("Error: " + errorMessage);
 

【讨论】:

【参考方案2】:

如果使用 C# 我创建成功 我的代码:

private  string WebServiceCall(string url)
        
            try
            
                Uri myUrl = new Uri(url);
                WebRequest webRequest = WebRequest.Create(myUrl);
                HttpWebRequest httpWebRequest = (HttpWebRequest)webRequest;
                httpWebRequest.Method = "POST";
                httpWebRequest.ContentType = "text/xml; charset=utf-8";
                httpWebRequest.Headers.Add("SOAPAction: LogsGet");
                httpWebRequest.ProtocolVersion = HttpVersion.Version11;

                //Credentials
                NetworkCredential myNetworkCredential = new NetworkCredential("admin", "admin");
                CredentialCache myCredentialCache = new CredentialCache();
                myCredentialCache.Add(myUrl, "Digest", myNetworkCredential);
                httpWebRequest.PreAuthenticate = true;
                httpWebRequest.Credentials = myNetworkCredential;
                Stream requestStream = httpWebRequest.GetRequestStream();
                //Create Stream and Complete Request             
                StreamWriter streamWriter = new StreamWriter(requestStream, Encoding.ASCII);

                StringBuilder soapRequest = new StringBuilder("<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\" ");
                soapRequest.Append("xmlns:log=\"LogsGet\" xmlns:mal=\"MalteseGlobal\" xmlns:job=\"JobGlobal\">");
                soapRequest.Append("<soapenv:Body>");
                soapRequest.Append("<log:LogsGetReq Cmd=\"Start\" OpV=\"01.00.00\" Sev=\"Info to critical\"/>");
                soapRequest.Append("</soapenv:Body></soapenv:Envelope>");

                streamWriter.Write(soapRequest.ToString());
                streamWriter.Close();
                //Get the Response    
                txtRequest.Text = soapRequest.ToString();
                HttpWebResponse wr = (HttpWebResponse)httpWebRequest.GetResponse();
                StreamReader srd = new StreamReader(wr.GetResponseStream());
                string resulXmlFromWebService = srd.ReadToEnd();
                return resulXmlFromWebService;
            
            catch (Exception e)
            
                return e.ToString();
            
        

【讨论】:

如果你会用Java写代码,你可以在这个话题上发帖。

以上是关于c#使用多线程发送HTTP请求的问题,高手进!~~~的主要内容,如果未能解决你的问题,请参考以下文章

高手进,关于C语言在windows上建立多线程的问题(VC6.0上实现)

java编程:java的多线程是怎么实现的?高手进吧

用于向 Web 服务发出 http post 请求的多线程

在c#中多线程处理大量Web请求

http请求和多线程

在多线程 HTTP 服务器中发送后,如何干净地关闭套接字?