async-await 是否可以与 C# 中的 tcp 文件传输一起使用?
Is async-await possible to be used with tcp file transfer in C#?
首先,请不要评判我,我是编程新手。我正在尝试制作一台 PC -> android 应用程序,将我 select 的文件发送到我的 phone。它有效,一切都很好,除了方法不是异步的。因此,如果我向我的 phone 发送内容,我的 UI 会冻结,直到发送完成。谁能帮我?我一直在阅读有关异步方法的所有文档,但我就是看不懂,我该如何实现它?
这是一些需要的代码:
这是 "sends" 文件的事件,我希望它是异步的。
private void button2_Click(object sender, EventArgs e) {
await push();
}
public async Task push() {
if (folder != null) {
string ip = textBox1.Text + "." + textBox2.Text + "." + textBox3.Text + "." + textBox4.Text;
listBox1.Items.Add("Creating a test server on the machine on port " + 8001 + ". Host ip: " + ip);
server = new Server(ip, 8001);
listBox1.Items.Add("Server running.");
int i = 0;
listBox1.Items.Add("Fetching files...");
getFileNum(folder, ref i);
listBox1.Items.Add("Files scanned. Current number: " + i + " files.");
//send number of files to be transmitted
listBox1.Items.Add("Getting your files ready... please standby.");
server.send(i.ToString());
listBox1.Items.Add("Your files are ready, beggining the transmitting process.");
//actual method for sending files
sendFiles(folder);
listBox1.Items.Add(".");
listBox1.Items.Add(".");
listBox1.Items.Add("Files sent!");
}
else {
MessageBox.Show("No directory path selected.", "Error_null_path");
}
}
public async Task<Task> sendFiles(DirectoryInfo dir) {
FileInfo[] files = dir.GetFiles();
DirectoryInfo[] dirs = dir.GetDirectories();
string path = dir.FullName + "/";
foreach (FileInfo file in files) {
await server.sendFile(path + file.Name, folder.FullName.Replace(folder.Name,""));
listBox1.Items.Add("Sent file: " + file.Name);
}
foreach (DirectoryInfo subDir in dirs) {
await sendFiles(subDir);
}
return null;
}
这是代码的发送部分,在"Server" class:
public async Task sendFile(string filePath, string root) {
FileInfo file = new FileInfo(filePath);
Socket server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
server.Bind(new IPEndPoint(IPAddress.Parse(ip), port));
//send song name length
server.Listen(0);
Socket client = server.Accept();
byte[] send;
if (filePath.Replace(root, "").Length < 10)
send = new UTF8Encoding(true).GetBytes("0" + filePath.Replace(root, "").Length);
else
send = new UTF8Encoding(true).GetBytes(filePath.Replace(root, "").Length.ToString());
client.Send(send);
client.Close();
server.Close();
//send song name
server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
server.Bind(new IPEndPoint(IPAddress.Parse(ip), port));
server.Listen(0);
client = server.Accept();
send = new UTF8Encoding(true).GetBytes(filePath.Replace(root,""));
client.Send(send);
client.Close();
server.Close();
//send the song
server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
server.Bind(new IPEndPoint(IPAddress.Parse(ip), port));
server.Listen(0);
client = server.Accept();
client.SendFile(file.FullName);
client.Close();
server.Close();
//return null;
}
public async Task send(string data) {
switch (data.Length) {
case 1:
data = "000" + data;
break;
case 2:
data = "00" + data;
break;
case 3:
data = "0" + data;
break;
default:
data = "0000";
break;
}
Socket server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
server.Bind(new IPEndPoint(IPAddress.Parse(ip), port));
server.Listen(0);
Socket client = server.Accept();
byte[] send = new UTF8Encoding(true).GetBytes(data);
client.Send(send);
client.Close();
server.Close();
//return null;
}
I'm pretty new to programming
提示:注意编译警告。他们会指出非常有用的东西。就像这段代码一样,会有一个编译器警告告诉你你标记了一个方法 async
但它会 运行 同步。
TCP/IP 套接字对于初学者来说非常复杂。哎呀,它们对于高级开发人员来说非常复杂。异步代码也很复杂,异步套接字是复杂的风暴。
因此,对于您的情况,既然您已经有了一个有效的解决方案,我会说使用 Task.Run
将您现有的同步代码推送到线程池线程。这是 UI 应用程序可接受的模式,但您不希望对任何类型的服务器应用程序(例如 ASP.NET)执行此操作。
public async Task push() {
...
var progress = new Progress<string>(report => listBox1.Items.Add(report));
await Task.Run(() => sendFiles(folder, progress));
listBox1.Items.Add(".");
listBox1.Items.Add(".");
listBox1.Items.Add("Files sent!");
...
}
public void sendFiles(DirectoryInfo dir, IProgress<string> progress) {
...
foreach (FileInfo file in files) {
server.sendFile(path + file.Name, folder.FullName.Replace(folder.Name,""));
progress?.Report("Sent file: " + file.Name);
}
foreach (DirectoryInfo subDir in dirs) {
sendFiles(subDir);
}
}
public void sendFile(string filePath, string root) {
...
}
这不是一个生产质量的解决方案,但它应该是一种模式,可以帮助您开始实现这一目标。
首先,请不要评判我,我是编程新手。我正在尝试制作一台 PC -> android 应用程序,将我 select 的文件发送到我的 phone。它有效,一切都很好,除了方法不是异步的。因此,如果我向我的 phone 发送内容,我的 UI 会冻结,直到发送完成。谁能帮我?我一直在阅读有关异步方法的所有文档,但我就是看不懂,我该如何实现它?
这是一些需要的代码:
这是 "sends" 文件的事件,我希望它是异步的。
private void button2_Click(object sender, EventArgs e) {
await push();
}
public async Task push() {
if (folder != null) {
string ip = textBox1.Text + "." + textBox2.Text + "." + textBox3.Text + "." + textBox4.Text;
listBox1.Items.Add("Creating a test server on the machine on port " + 8001 + ". Host ip: " + ip);
server = new Server(ip, 8001);
listBox1.Items.Add("Server running.");
int i = 0;
listBox1.Items.Add("Fetching files...");
getFileNum(folder, ref i);
listBox1.Items.Add("Files scanned. Current number: " + i + " files.");
//send number of files to be transmitted
listBox1.Items.Add("Getting your files ready... please standby.");
server.send(i.ToString());
listBox1.Items.Add("Your files are ready, beggining the transmitting process.");
//actual method for sending files
sendFiles(folder);
listBox1.Items.Add(".");
listBox1.Items.Add(".");
listBox1.Items.Add("Files sent!");
}
else {
MessageBox.Show("No directory path selected.", "Error_null_path");
}
}
public async Task<Task> sendFiles(DirectoryInfo dir) {
FileInfo[] files = dir.GetFiles();
DirectoryInfo[] dirs = dir.GetDirectories();
string path = dir.FullName + "/";
foreach (FileInfo file in files) {
await server.sendFile(path + file.Name, folder.FullName.Replace(folder.Name,""));
listBox1.Items.Add("Sent file: " + file.Name);
}
foreach (DirectoryInfo subDir in dirs) {
await sendFiles(subDir);
}
return null;
}
这是代码的发送部分,在"Server" class:
public async Task sendFile(string filePath, string root) {
FileInfo file = new FileInfo(filePath);
Socket server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
server.Bind(new IPEndPoint(IPAddress.Parse(ip), port));
//send song name length
server.Listen(0);
Socket client = server.Accept();
byte[] send;
if (filePath.Replace(root, "").Length < 10)
send = new UTF8Encoding(true).GetBytes("0" + filePath.Replace(root, "").Length);
else
send = new UTF8Encoding(true).GetBytes(filePath.Replace(root, "").Length.ToString());
client.Send(send);
client.Close();
server.Close();
//send song name
server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
server.Bind(new IPEndPoint(IPAddress.Parse(ip), port));
server.Listen(0);
client = server.Accept();
send = new UTF8Encoding(true).GetBytes(filePath.Replace(root,""));
client.Send(send);
client.Close();
server.Close();
//send the song
server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
server.Bind(new IPEndPoint(IPAddress.Parse(ip), port));
server.Listen(0);
client = server.Accept();
client.SendFile(file.FullName);
client.Close();
server.Close();
//return null;
}
public async Task send(string data) {
switch (data.Length) {
case 1:
data = "000" + data;
break;
case 2:
data = "00" + data;
break;
case 3:
data = "0" + data;
break;
default:
data = "0000";
break;
}
Socket server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
server.Bind(new IPEndPoint(IPAddress.Parse(ip), port));
server.Listen(0);
Socket client = server.Accept();
byte[] send = new UTF8Encoding(true).GetBytes(data);
client.Send(send);
client.Close();
server.Close();
//return null;
}
I'm pretty new to programming
提示:注意编译警告。他们会指出非常有用的东西。就像这段代码一样,会有一个编译器警告告诉你你标记了一个方法 async
但它会 运行 同步。
TCP/IP 套接字对于初学者来说非常复杂。哎呀,它们对于高级开发人员来说非常复杂。异步代码也很复杂,异步套接字是复杂的风暴。
因此,对于您的情况,既然您已经有了一个有效的解决方案,我会说使用 Task.Run
将您现有的同步代码推送到线程池线程。这是 UI 应用程序可接受的模式,但您不希望对任何类型的服务器应用程序(例如 ASP.NET)执行此操作。
public async Task push() {
...
var progress = new Progress<string>(report => listBox1.Items.Add(report));
await Task.Run(() => sendFiles(folder, progress));
listBox1.Items.Add(".");
listBox1.Items.Add(".");
listBox1.Items.Add("Files sent!");
...
}
public void sendFiles(DirectoryInfo dir, IProgress<string> progress) {
...
foreach (FileInfo file in files) {
server.sendFile(path + file.Name, folder.FullName.Replace(folder.Name,""));
progress?.Report("Sent file: " + file.Name);
}
foreach (DirectoryInfo subDir in dirs) {
sendFiles(subDir);
}
}
public void sendFile(string filePath, string root) {
...
}
这不是一个生产质量的解决方案,但它应该是一种模式,可以帮助您开始实现这一目标。