Честно говоря, это кажется, что у Вас уже есть большинство оснований, охваченных.
+44 (0) 800 форматов, иногда (неправильно) используемых в Великобритании, являются раздражающими и не являются строго допустимыми согласно E.123, который является рекомендацией ITU-T для того, как должны быть отображены числа. Если у Вас нет копии E.123, он достойный внимания.
Если это имеет значение, сама телефонная сеть не всегда использует E.164. Часто будет флаг в ISDN передача сигналов сгенерированном PBX (или в сети, если Вы будете по паровому телефону), который говорит сеть, является ли набираемое число локальным, национальным или международным.
Чтобы справиться с этим, вам нужно будет использовать обратный вызов из чтения NetStream. И, честно говоря, было бы проще поместить логику копирования в отдельный класс, чтобы вы могли поддерживать экземпляр активных потоков.
Я бы подошел к этому так (не тестировалось):
public class Assignment1
{
public static void NetToFile(NetworkStream net, FileStream file)
{
var copier = new AsyncStreamCopier(net, file);
copier.Start();
}
public static void NetToFile_Option2(NetworkStream net, FileStream file)
{
var completedEvent = new ManualResetEvent(false);
// copy as usual but listen for completion
var copier = new AsyncStreamCopier(net, file);
copier.Completed += (s, e) => completedEvent.Set();
copier.Start();
completedEvent.WaitOne();
}
/// <summary>
/// The Async Copier class reads the input Stream Async and writes Synchronously
/// </summary>
public class AsyncStreamCopier
{
public event EventHandler Completed;
private readonly Stream input;
private readonly Stream output;
private byte[] buffer = new byte[4096];
public AsyncStreamCopier(Stream input, Stream output)
{
this.input = input;
this.output = output;
}
public void Start()
{
GetNextChunk();
}
private void GetNextChunk()
{
input.BeginRead(buffer, 0, buffer.Length, InputReadComplete, null);
}
private void InputReadComplete(IAsyncResult ar)
{
// input read asynchronously completed
int bytesRead = input.EndRead(ar);
if (bytesRead == 0)
{
RaiseCompleted();
return;
}
// write synchronously
output.Write(buffer, 0, bytesRead);
// get next
GetNextChunk();
}
private void RaiseCompleted()
{
if (Completed != null)
{
Completed(this, EventArgs.Empty);
}
}
}
}
You're right, what you're doing is basically synchronous reading, because you use the WaitOne() method and it just stops the execution until the data is ready, that's basically the same as doing it using Read() instead of BeginRead() and EndRead().
What you have to do, is use the callback argument in the BeginRead() method, with it, you define a callback method (or a lambda expression), this method will be invoked when the information has been read (in the callback method you have to check for the end of the stream, and write to the output stream), this way you won't be blocking the main thread (you won't need the WaitOne() nor the EndRead().
Hope this helps.