Search code examples
c#wpfasynchronousstream

Is it some way to do async code for write to Stream?


I wrote some WPF editor, which show come text. But text stores at Stream.

So, here XAML code:

<TextBox Text="{Binding ObjectViewModel.Text,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" />

I set UpdateSourceTrigger to PropertyChanged, because user can read and write some text at this redactor;

Here code where read and write text (as stream):

public String Text
{
    get
    {    
        var sr = new StreamReader(StreamObject.text, Encoding.UTF8, true);
        return sr.ReadToEnd();
    }

    set
    {
        lock (_lockObject)
        {
            var str = value;
            var textStream = new MemoryStream();
            using (var writer = new BinaryWriter(textStream, Encoding.UTF8, true))
            {                                           
                writer.Write(Encoding.UTF8.GetBytes(str));
            }
            textStream.Position = 0;
            StreamObject.text = null;
            StreamObject.text = textStream;
            textStream.Close();
        }
    }
}

So, when user type new word- code write to stream new data (clear old stream and create new).

But it get slow performance. Should I use async (somehow) or other method to make performance better?

I know, that can use LostFocus property, but at that way user should to lost focus of TextBox.


Solution

  • Should i use async (somehow) or other method to make perfomace better?

    There is indeed an async version of the ReadToEnd method called ReadToEndAsync but it won't actually make your code any faster and you cannot call it from a property since properties cannot be marked as async.

    It makes no sense to create a new Stream in the getter of the source property and in the setter of the same each time the property is changed.

    You should read from the stream once, for example in the constructor of the view model or the Execute method of a command, and then set the value of the string property. Then you convert the string back to a stream once by the time you actually need to save it to the database, e.g:

    class ViewModel
    {
        public ViewModel()
        {
            using (var sr = new StreamReader(StreamObject.text, Encoding.UTF8, true))
                Text = sr.ReadToEnd();
        }
    
        //this method is called when your "Save" button or similar is clicked
        public void SaveToDb()
        {
            lock (_lockObject)
            {
                var str = value;
                using (textStream = new MemoryStream())
                {
                    using (var writer = new BinaryWriter(textStream, Encoding.UTF8, true))
                    {
                        writer.Write(Encoding.UTF8.GetBytes(str));
                    }
                    textStream.Position = 0;
                    StreamObject.text = null;
                    StreamObject.text = textStream;
                }
            }
        }
    
        public String Text
        {
            get;set;
        }
    }
    

    The source property itself should not know anything about the stream.