First of all, don't judge me, please, I'm pretty new to programming. I am trying to make a PC -> android app that sends files I select to my phone. It works, everything is fine, except that the methods aren't asynchronous. So, if I send something to my phone, my UI freezes until the sending is done. Can anyone help me? I've been reading all the docs for the async methods but i just can't get it, how do I implement it?
Here's some needed code:
This is the event that "sends" files, I want it to be async.
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;
}
this is the sending part of the code, in the "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
Tip: pay attention to compiler warnings. They'll point out very useful things. Like for this code, there will be a compiler warning telling you that you marked a method async
but it will run synchronously.
TCP/IP sockets are very complex for a beginner. Heck, they're very complex for advanced developers. Asynchronous code is also complex, and asynchronous sockets are a firestorm of complexity.
So, for your case, since you already have a solution working, I would say to use Task.Run
to push your existing synchronous code to a thread pool thread. This is an acceptable pattern for UI applications, but you wouldn't want to do this for any kind of a server app (eg, 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) {
...
}
This is not a production-quality solution, but it should be a pattern that can get you started towards one.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.