<window x:class="wpfapplication1.mainwindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:wpfapplication1"
        mc:ignorable="d"
        title="mainwindow" height="350" width="525">
    <grid>
        <grid.rowdefinitions>
            <rowdefinition/>
            <rowdefinition/>
            <rowdefinition/>
        </grid.rowdefinitions>
        <grid.columndefinitions>
            <columndefinition/>
            <columndefinition/>
        </grid.columndefinitions>
        <button grid.row="0" grid.column="0" command="{binding clickcmd}" content="click cmd"/>
        <button grid.row="0" grid.column="1" command="{binding cancelcmd}" content="cancel cmd"/>
        <listbox grid.row="1" borderbrush="black" borderthickness="3" grid.rowspan="2" itemssource="{binding contentob,mode=twoway,updatesourcetrigger=propertychanged}"/>
    </grid>
</window>
using system;
using system.collections.generic;
using system.linq;
using system.text;
using system.threading.tasks;
using system.windows.input;

namespace wpfapplication1.model
{
    public class delegatecommand : icommand
    {
        private readonly predicate<object> _canexecute;
        private readonly action<object> _execute;

        public event eventhandler canexecutechanged;

        public delegatecommand(action<object> execute)
                       : this(execute, null)
        {
        }

        public delegatecommand(action<object> execute,
                       predicate<object> canexecute)
        {
            _execute = execute;
            _canexecute = canexecute;
        }

        public  bool canexecute(object parameter)
        {
            if (_canexecute == null)
            {
                return true;
            }

            return _canexecute(parameter);
        }

        public  void execute(object parameter)
        {
            _execute(parameter);
        }

        public void raisecanexecutechanged()
        {
            if (canexecutechanged != null)
            {
                canexecutechanged(this, eventargs.empty);
            }
        }
    }
}
 using system;
using system.collections.generic;
using system.linq;
using system.text;
using system.threading.tasks;
using system.componentmodel;
using wpfapplication1.model;
using system.collections.objectmodel;
using system.threading;
using system.windows; 
using system.io;
using newtonsoft.json;

namespace wpfapplication1.viewmodel
{
    public class wpfvm : inotifypropertychanged
    {
        private wpfvm()
        {

        }
        public event propertychangedeventhandler propertychanged;

        public void onpropertychanged(string propname)
        {
            var handler = propertychanged;
            if(handler!=null)
            {
                handler?.invoke(this, new propertychangedeventargs(propname));
            }
        }

        private static wpfvm wpfvm;
        private static readonly object objlock = new object();
        public static wpfvm getwpfvm()
        {
            lock(objlock)
            {
                if(wpfvm == null)
                {
                    wpfvm = new wpfvm();
                }
                return wpfvm;
            }
        }

        private static cancellationtokensource cts=new cancellationtokensource();

        #region commands
        private delegatecommand clickcmdvalue;
        public delegatecommand clickcmd
        {
            get
            {
                if(clickcmdvalue==null)
                {
                    clickcmdvalue = new delegatecommand(clickcmdexecuted);
                }
                return clickcmdvalue;
            }
        }

        private string contentvalue;
        public string content
        {
            get
            {
                return contentvalue;
            }
            set
            {
                if(value!=contentvalue)
                {
                    contentvalue = value;
                    onpropertychanged("content");
                }
            }
        }


        private bool iscancelledvalue=false;
        public bool iscancelled
        {
            get
            {
                return iscancelledvalue;
            }
            set
            {
                if(value!=iscancelledvalue)
                {
                    iscancelledvalue = value;
                    onpropertychanged("iscancelled");
                }
            }
        }
        private void clickcmdexecuted(object obj)
        {
            contentob = new observablecollection<string>();
            task.run(() =>
            {
                while (!cts.iscancellationrequested)
                {
                    content = datetime.now.tostring("yyyymmddhhmmssffff");
                    app.current.dispatcher.begininvoke((action)delegate
                    {
                        contentob.add(content);
                    });
                    system.diagnostics.debug.writeline(content);
                }
            },cts.token);                      
        }

        private delegatecommand cancelcmdvalue;
        public delegatecommand cancelcmd
        {
            get
            {
                if(cancelcmdvalue==null)
                {
                    cancelcmdvalue = new delegatecommand(cancelcmdvalueexecuted);
                }
                return cancelcmdvalue;
            }
        }

        private void cancelcmdvalueexecuted(object obj)
        {
            cts.cancel();
            iscancelled = true;
            system.diagnostics.debug.writeline("cancelled!");
            string msjsonserializerstring = jsonconvert.serializeobject(contentob,formatting.indented);
            string filename = datetime.now.tostring("yyyymmddhhmmssffff") + ".txt";
            using(streamwriter streamwriter=new streamwriter(filename,true,encoding.utf8))
            {
                streamwriter.writeline(msjsonserializerstring);
            }
        }
        #endregion

        #region properties
        private observablecollection<string> contentobvalue;
        public observablecollection<string> contentob
        {
            get
            {                 
                return contentobvalue;
            }
            set
            {
                if(value!=contentobvalue)
                {
                    contentobvalue = value;
                    onpropertychanged("contentob");
                }
            }
        }
        #endregion
    }
}
 1 using system;
 2 using system.collections.generic;
 3 using system.linq;
 4 using system.text;
 5 using system.threading.tasks;
 6 using system.windows;
 7 using system.windows.controls;
 8 using system.windows.data;
 9 using system.windows.documents;
10 using system.windows.input;
11 using system.windows.media;
12 using system.windows.media.imaging;
13 using system.windows.navigation;
14 using system.windows.shapes;
15 using wpfapplication1.viewmodel;
16 
17 namespace wpfapplication1
18 {
19     /// <summary>
20     /// interaction logic for mainwindow.xaml
21     /// </summary>
22     public partial class mainwindow : window
23     {
24         public mainwindow()
25         {
26             initializecomponent();
27             wpfvm vm = wpfvm.getwpfvm();
28             this.datacontext = vm;
29         }
30     }
31 }

private void clickcmdexecuted(object obj)
{
contentob = new observablecollection<string>();
task.run(() =>
{
while (!cts.iscancellationrequested)
{
content = datetime.now.tostring(“yyyymmddhhmmssffff”);
app.current.dispatcher.begininvoke((action)delegate
{
contentob.add(content);
});
system.diagnostics.debug.writeline(content);
}
},cts.token);
}