我正在开发一个程序,它允许您选择多个xml文件并将其发送到Web服务器。
发送的每个xml文件数据都将在一个线程上运行,因此数据发送并行运行。我遇到的问题是,当我输入第一个文件时,它会提前响应,甚至不会输入下一个文件。
我不知道如何让所有线程等到我在同一个线程上一次性输入所有线程。我尝试了下面的一个实现但是在输入第一个文件后它响应得太早了。
继承我的代码:
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Xml;
namespace XMLSender
{
class Program
{
private static string serverUrl;
static void Main(string[] args)
{
Console.WriteLine("Please enter the URL to send the XML File");
serverUrl = Console.ReadLine();
List<Thread> threads = new List<Thread>();
string fileName = "";
do
{
Console.WriteLine("Please enter the XML File you Wish to send");
fileName = Console.ReadLine();
Thread t = new Thread(new ParameterizedThreadStart(send));
threads.Add(t);
}
while (fileName != "start"); //Ends if user enters an empty line
foreach (Thread t in threads)
{
t.Start();
}
foreach (Thread t in threads)
{
t.Join();
}
}
static private void send(object data)
{
try
{
//ServicePointManager.ServerCertificateValidationCallback = delegate { return true; };
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(serverUrl);
byte[] bytes;
//Load XML data from document
XmlDocument doc = new XmlDocument();
doc.Load((string)data);
string xmlcontents = doc.InnerXml;
//Send XML data to Webserver
bytes = Encoding.ASCII.GetBytes(xmlcontents);
request.ContentType = "text/xml; encoding='utf-8'";
request.ContentLength = bytes.Length;
request.Method = "POST";
Stream requestStream = request.GetRequestStream();
requestStream.Write(bytes, 0, bytes.Length);
requestStream.Close();
// Get response from Webserver
HttpWebResponse response;
response = (HttpWebResponse)request.GetResponse();
Stream responseStream = response.GetResponseStream();
string responseStr = new StreamReader(responseStream).ReadToEnd();
Console.Write(responseStr + Environment.NewLine);
}
catch (Exception e)
{
Console.WriteLine("An Error Occured" + Environment.NewLine + e);
Console.ReadLine();
}
}
}
}
答案 0 :(得分:2)
如果你想一次启动所有线程,在你的do-while循环中,不要启动线程。 (不要叫t.Start())
相反,在此期间将文件名保存在列表中,然后在while循环之后放置另一个foreach循环,然后启动所有线程:
string fileName = "";
List<string> names = new List<string>();
do
{
Console.WriteLine("Please enter the XML File you Wish to send");
fileName = Console.ReadLine();
if(fileName != "start")
{
Thread t = new Thread(new ParameterizedThreadStart(send));
threads.Add(t);
names.Add(fileName);
}
}
while (fileName != "start");
foreach (Thread t in threads)
{
t.Start(names[0]);
names.RemoveAt(0);
}
编辑:我添加了一项检查,以确保在输入start时不添加其他线程,因为即使循环条件不再为真,循环仍将完成。<登记/>
如果没有检查,则会添加一个新线程,并以start
作为参数添加结尾。
答案 1 :(得分:2)
首先,创建一个ManulResetEvent
。此事件可以使线程等到某个事件发生。然后在允许所有线程继续时触发ManulResetEvent
。像这样:
class Program
{
private static readonly ManualResetEvent _wait = new ManualResetEvent(false);
...
在你的线程代码中,让所有线程等待:
static private void send(object data)
{
_wait.WaitOne();
...
在Main-method中输入所有文件后触发事件:
...
while (fileName != ""); //Ends if user enters an empty line
_wait.Set()
foreach (Thread t in threads)
...
答案 2 :(得分:1)
第二个解决方案可能是在不启动它们的情况下初始化线程,但是使用filename-parameter:
...
filename = Console.ReadLine();
Thread t = new Thread(() => send(filename));
threads.Add(t);
...
在你的循环之外,你开始所有的线程:
foreach (Thread t in threads)
{
t.Start();
}