Showing posts with label .NET35. Show all posts
Showing posts with label .NET35. Show all posts

Thursday, April 9, 2020

Async Await Non BLocking UI from OLD HTTPWEBREQUEST

 


 

Taken from https://stackoverflow.com/questions/14577346/converting-ordinary-http-post-web-request-with-async-and-await

from answer https://stackoverflow.com/a/14711326 

There 4 await, even StreamReader WILL BLOCK your UI ( Gw baru tahu disini, ketika koneksi DOWN and SLOW . Internet Provider in village is sucks ) & GetRequestStreamAsync is must




public async Task GetEnvironmentVariablesAsync(Action<Credentials> getResultCallback, Action<Exception> getErrorCallback)
{
    CredentialsCallback = getResultCallback;
    ErrorCallback = getErrorCallback;
    var uri = new Uri(BaseUri);
    var request = (HttpWebRequest) WebRequest.Create(uri);
    request.Method = "POST";
    request.ContentType = "application/json";
    var jsonObject = new JObject
    {
        new JProperty("apiKey",_api),
        new JProperty("affiliateId",_affid),
    };
    var serializedResult = JsonConvert.SerializeObject(jsonObject);
    byte[] requestBody = Encoding.UTF8.GetBytes(serializedResult);

    // ASYNC: using awaitable wrapper to get request stream
    using (var postStream = await request.GetRequestStreamAsync())
    {
        // Write to the request stream.
        // ASYNC: writing to the POST stream can be slow
        await postStream.WriteAsync(requestBody, 0, requestBody.Length);
    }

    try
    {
        // ASYNC: using awaitable wrapper to get response
        var response = (HttpWebResponse) await request.GetResponseAsync();
        if (response != null)
        {
            var reader = new StreamReader(response.GetResponseStream());
            // ASYNC: using StreamReader's async method to read to end, in case
            // the stream i slarge.
            string responseString = await reader.ReadToEndAsync();
            Credentails = JsonConvert.DeserializeObject<Credentials>(responseString);
            if (Credentails != null && string.IsNullOrEmpty(Credentails.Err))
                CredentialsCallback(Credentails);
            else
            {
                if (Credentails != null)
                    ErrorCallback(new Exception(string.Format("Error Code : {0}", StorageCredentails.Err)));
            }
        }
    }
    catch (WebException we)
    {
        var reader = new StreamReader(we.Response.GetResponseStream());
        string responseString = reader.ReadToEnd();
        Debug.WriteLine(responseString);
        ErrorCallback(we);

    }
}


This is MY OWN IMPLEMENTATION



private async Task<string> REQUESTBLOCK( string blogid, string bearer)
{

string responseresult = string.Empty;

try
{



 HttpWebRequest request = (HttpWebRequest)WebRequest.Create("https:/website/");

 request.UserAgent = "Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:74.0) Gecko/20100101 Firefox/74.0";
 request.Accept = "*/*";
 request.Headers.Set(HttpRequestHeader.AcceptLanguage, "en-US,en;q=0.5");
 request.Headers.Set(HttpRequestHeader.AcceptEncoding, "gzip, deflate, br");
 request.Referer = "https:/website/" + blogid + "/write/new";
 request.ContentType = "application/json";
 request.Headers.Set(HttpRequestHeader.Authorization, bearer);
 request.Headers.Add("X-Client-Release", @"RELEASE");
 request.Headers.Add("X-Client-Request-Id", @"IDCLIENT");
 request.Headers.Add("Origin", @"https:/website/");
 request.KeepAlive = true;

 request.Method = "POST";
 request.ServicePoint.Expect100Continue = false;


 string body = @"DISINIJSON";
 byte[] postBytes = System.Text.Encoding.UTF8.GetBytes(body);
 request.ContentLength = postBytes.Length;
 Stream stream = await request.GetRequestStreamAsync();
 stream.Write(postBytes, 0, postBytes.Length);
 stream.Close();

 using (var response = await request.GetResponseAsync())
 {
  using (Stream dataStream = response.GetResponseStream())
  {
   // Open the stream using a StreamReader for easy access.  
   StreamReader reader = new StreamReader(dataStream);
   // Read the content.  
   string responseFromServer = await reader.ReadToEndAsync();
   // Display the content.  
   //Console.WriteLine(responseFromServer);

   responseresult = responseFromServer;
   //Console.WriteLine(dataurl);
  }

 }

}  
 catch  /*(WebException e) */
 {

 }

}

Thursday, February 6, 2020

Scraper GoodReads, Ebook Scraper








Scraper GoodReads, Ebook Scraper, result come with 3 different data, ID, LINK, TITLE.

GOODREADS:
Goodreads is the world’s largest site for readers and book recommendations. Our mission is to help people find and share books they love. Goodreads launched in January 2007. 

Btw the scraper will randomly delay between 5 second to 30 seconds.

Btw dont forget to join us in our FB GROUPS


ScreenSHOT





Requirement 

NET 4.6.1 and atleast WINDOWS 7

 Scraper GoodReads v1.1

https://www.mediafire.com/file/hhroeqayz2dzzsd/Scraper_GoodReads_v1.0.zip/file
https://www.mediafire.com/file/hhroeqayz2dzzsd/Scraper_GoodReads_v1.0.zip/file
https://www.mediafire.com/file/hhroeqayz2dzzsd/Scraper_GoodReads_v1.0.zip/file
https://www.mediafire.com/file/hhroeqayz2dzzsd/Scraper_GoodReads_v1.0.zip/file

Monday, September 10, 2018

Better Way to opening folder C#

 
 
using System;
using System.Reflection;
using System.Windows.Forms;

class OpenFolderDialog
{
    //public bool AddExtension { get; set; }
    public bool AutoUpgradeEnabled { get; set; }
    //public bool CheckFileExists { get; set; }
    public bool CheckPathExists { get; set; }
    //public bool DereferenceLinks { get; set; }
    public string Title { get; set; }
    //public string DefaultExt { get; set; }
    public string InitialDirectory { get; set; }
    //public bool ValidateNames { get; set; }
    //public bool SupportMultiDottedExtensions { get; set; }
    //public bool ShowHelp { get; set; }
    public bool Multiselect { get; set; }
    public bool RestoreDirectory { get; set; }
    //public string Filter { get; set; }
    public string SelectedPath { get; private set; }
    public string[] SelectedPaths { get; private set; }

    private FolderBrowserDialog FolderBrowser
    {
        get
        {
            return new FolderBrowserDialog()
            {
                ShowNewFolderButton = true,
                Description = Title,
                SelectedPath = InitialDirectory
            };
        }
    }

    private OpenFileDialog Dialog
    {
        get
        {
            return new OpenFileDialog()
            {
                Title = Title,
                AddExtension = false,
                AutoUpgradeEnabled = AutoUpgradeEnabled,
                CheckFileExists = true,
                CheckPathExists = CheckPathExists,
                DefaultExt = string.Empty,
                DereferenceLinks = false,
                InitialDirectory = InitialDirectory,
                ValidateNames = false,
                SupportMultiDottedExtensions = false,
                ShowHelp = false,
                Multiselect = Multiselect,
                RestoreDirectory = RestoreDirectory,
                Filter = string.Empty,
                FileName = SelectedPath
            };
        }
    }

    /// Handle of the control or window to be the parent of the file dialog
    /// true if the user clicks OK
    public DialogResult ShowDialog(IntPtr hWndOwner)
    {
        if (Environment.OSVersion.Version.Major >= 6)
        {
            OpenFileDialog dialog = Dialog;
            DialogResult result = VistaDialog.Show(hWndOwner, dialog) != 0 ? DialogResult.Cancel : DialogResult.OK;
            SelectedPath = dialog.FileName;
            SelectedPaths = dialog.FileNames;
            return result;
        }
        else
        {
            FolderBrowserDialog XPDialog = FolderBrowser;
            DialogResult result = XPDialog.ShowDialog();
            SelectedPath = XPDialog.SelectedPath;
            return result;
        }
    }

    private static class VistaDialog
    {
        private const BindingFlags c_flags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
        private readonly static Assembly s_windowsFormsAssembly = typeof(FileDialog).Assembly;
        private readonly static Type s_iFileDialogType = s_windowsFormsAssembly.GetType("System.Windows.Forms.FileDialogNative+IFileDialog");
        private readonly static MethodInfo s_createVistaDialogMethodInfo = typeof(OpenFileDialog).GetMethod("CreateVistaDialog", c_flags);
        private readonly static MethodInfo s_onBeforeVistaDialogMethodInfo = typeof(OpenFileDialog).GetMethod("OnBeforeVistaDialog", c_flags);
        private readonly static MethodInfo s_getOptionsMethodInfo = typeof(FileDialog).GetMethod("GetOptions", c_flags);
        private readonly static MethodInfo s_setOptionsMethodInfo = s_iFileDialogType.GetMethod("SetOptions", c_flags);
        private readonly static uint s_fosPickFoldersBitFlag = (uint)s_windowsFormsAssembly
            .GetType("System.Windows.Forms.FileDialogNative+FOS")
            .GetField("FOS_PICKFOLDERS")
            .GetValue(null);
        private readonly static ConstructorInfo s_vistaDialogEventsConstructorInfo = s_windowsFormsAssembly
            .GetType("System.Windows.Forms.FileDialog+VistaDialogEvents")
            .GetConstructor(c_flags, null, new[] { typeof(FileDialog) }, null);
        private readonly static MethodInfo s_adviseMethodInfo = s_iFileDialogType.GetMethod("Advise");
        private readonly static MethodInfo s_unAdviseMethodInfo = s_iFileDialogType.GetMethod("Unadvise");
        private readonly static MethodInfo s_showMethodInfo = s_iFileDialogType.GetMethod("Show");

        public static int Show(IntPtr ownerHandle, OpenFileDialog dialog)
        {
            var iFileDialog = s_createVistaDialogMethodInfo.Invoke(dialog, new object[] { });
            s_onBeforeVistaDialogMethodInfo.Invoke(dialog, new[] { iFileDialog });
            s_setOptionsMethodInfo.Invoke(iFileDialog, new object[] { (uint)s_getOptionsMethodInfo.Invoke(dialog, new object[] { }) | s_fosPickFoldersBitFlag });
            var adviseParametersWithOutputConnectionToken = new[] { s_vistaDialogEventsConstructorInfo.Invoke(new object[] { dialog }), 0U };
            s_adviseMethodInfo.Invoke(iFileDialog, adviseParametersWithOutputConnectionToken);

            try
            {
                return (int)s_showMethodInfo.Invoke(iFileDialog, new object[] { ownerHandle });

            }
            finally
            {
                s_unAdviseMethodInfo.Invoke(iFileDialog, new[] { adviseParametersWithOutputConnectionToken[1] });
            }
        }
    }
}
usage
OpenFolderDialog folder = new OpenFolderDialog()
            {
                Title = "Select destination folder",
                AutoUpgradeEnabled = true,
                CheckPathExists = true,
                InitialDirectory =
                Environment.GetFolderPath
                (Environment.SpecialFolder.DesktopDirectory),
                Multiselect = false,
                RestoreDirectory = true
            };
            DialogResult result = folder.ShowDialog(IntPtr.Zero);
            if (result.Equals(DialogResult.OK))
            {
                //MessageBox.Show(folder.SelectedPath + " Paths:" + folder.SelectedPaths.Length);
                textBox1.Text = folder.SelectedPath;
            }

Monday, July 23, 2018

NOTES for js in C#

 


 

https://stackoverflow.com/questions/49015061/anglesharp-run-all-javascript-before-looking-for-element

var config = AngleSharp.Configuration.Default.WithDefaultLoader().WithCookies().WithJavaScript().WithCss();
            var browsingContext = BrowsingContext.New(config);

            await browsingContext.OpenAsync("https://users.premierleague.com/");
            await browsingContext.Active.QuerySelector("form[action='/accounts/login/']").SubmitAsync(new
            {
                login = "abc@gmail.com",
                password = "password"
            });
            await browsingContext.OpenAsync("https://fantasy.premierleague.com/a/team/my/");
   
foreach (var element in elements)
            {
                var scripts = element.GetElementsByTagName("script");
                
                foreach(var script in scripts)
                {
                    script.Parent.RemoveChild(script);
                }
            }
https://stackoverflow.com/questions/18156795/parsing-html-to-get-script-variable-value/18157325#18157325
var html = @"
             // Some HTML
             
             // More HTML
             ";

// Grab the content of the first script element
HtmlAgilityPack.HtmlDocument doc = new HtmlAgilityPack.HtmlDocument();
doc.LoadHtml(html);
var script = doc.DocumentNode.Descendants()
                             .Where(n => n.Name == "script")
                             .First().InnerText;

// Return the data of spect and stringify it into a proper JSON object
var engine = new Jurassic.ScriptEngine();
var result = engine.Evaluate("(function() { " + script + " return spect; })()");
var json = JSONObject.Stringify(engine, result);

Console.WriteLine(json);
Console.ReadKey();
Output:
https://github.com/paulbartrum/jurassic
http://html-agility-pack.net/

https://stackoverflow.com/questions/20930414/how-to-dynamically-generate-html-code-using-nets-webbrowser-or-mshtml-htmldocu/20934538#20934538

https://stackoverflow.com/questions/21697048/how-to-fix-a-opacity-bug-with-drawtobitmap-on-webbrowser-control/21828265#21828265

Sunday, August 20, 2017

Radiobutton requires clicking twice when databound

Taken from here https://stackoverflow.com/questions/19052725/radiobutton-requires-clicking-twice-when-databound


In the click event:
private void RadioButtonClick(object sender, EventArgs e)
{
    var rb = sender as RadioButton;
    if (rb != null && !rb.Checked)
    {
        rb.Checked = !rb.Checked;
    }
}
More read http://www.whilenotdeadlearn.com/blog/2008/07/surviving-winforms-databinding

2008 until 2017 ( this note ). Still exist until now.

Monday, August 22, 2016

Kill Child Process When Parent Exit C#


 

 

Taken from
http://stackoverflow.com/questions/3342941/kill-child-process-when-parent-process-is-killed

for My NOTE



/// <summary>
/// Allows processes to be automatically killed if this parent process unexpectedly quits.
/// This feature requires Windows 8 or greater. On Windows 7, nothing is done.</summary>
/// <remarks>References:
///  http://stackoverflow.com/a/4657392/386091
///  http://stackoverflow.com/a/9164742/386091 </remarks>
public static class ChildProcessTracker
{
    /// <summary>
    /// Add the process to be tracked. If our current process is killed, the child processes
    /// that we are tracking will be automatically killed, too. If the child process terminates
    /// first, that's fine, too.</summary>
    /// <param name="process"></param>
    public static void AddProcess(Process process)
    {
        if (s_jobHandle != IntPtr.Zero)
        {
            bool success = AssignProcessToJobObject(s_jobHandle, process.Handle);
            if (!success)
                throw new Win32Exception();
        }
    }

    static ChildProcessTracker()
    {
        // This feature requires Windows 8 or later. To support Windows 7 requires
        //  registry settings to be added if you are using Visual Studio plus an
        //  app.manifest change.
        //  http://stackoverflow.com/a/4232259/386091
        //  http://stackoverflow.com/a/9507862/386091
        if (Environment.OSVersion.Version < new Version(6, 2))
            return;

        // The job name is optional (and can be null) but it helps with diagnostics.
        //  If it's not null, it has to be unique. Use SysInternals' Handle command-line
        //  utility: handle -a ChildProcessTracker
        string jobName = "ChildProcessTracker" + Process.GetCurrentProcess().Id;
        s_jobHandle = CreateJobObject(IntPtr.Zero, jobName);

        var info = new JOBOBJECT_BASIC_LIMIT_INFORMATION();

        // This is the key flag. When our process is killed, Windows will automatically
        //  close the job handle, and when that happens, we want the child processes to
        //  be killed, too.
        info.LimitFlags = JOBOBJECTLIMIT.JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE;

        var extendedInfo = new JOBOBJECT_EXTENDED_LIMIT_INFORMATION();
        extendedInfo.BasicLimitInformation = info;

        int length = Marshal.SizeOf(typeof(JOBOBJECT_EXTENDED_LIMIT_INFORMATION));
        IntPtr extendedInfoPtr = Marshal.AllocHGlobal(length);
        try
        {
            Marshal.StructureToPtr(extendedInfo, extendedInfoPtr, false);

            if (!SetInformationJobObject(s_jobHandle, JobObjectInfoType.ExtendedLimitInformation,
                extendedInfoPtr, (uint)length))
            {
                throw new Win32Exception();
            }
        }
        finally
        {
            Marshal.FreeHGlobal(extendedInfoPtr);
        }
    }

    [DllImport("kernel32.dll", CharSet = CharSet.Unicode)]
    static extern IntPtr CreateJobObject(IntPtr lpJobAttributes, string name);

    [DllImport("kernel32.dll")]
    static extern bool SetInformationJobObject(IntPtr job, JobObjectInfoType infoType,
        IntPtr lpJobObjectInfo, uint cbJobObjectInfoLength);

    [DllImport("kernel32.dll", SetLastError = true)]
    static extern bool AssignProcessToJobObject(IntPtr job, IntPtr process);

    // Windows will automatically close any open job handles when our process terminates.
    //  This can be verified by using SysInternals' Handle utility. When the job handle
    //  is closed, the child processes will be killed.
    private static readonly IntPtr s_jobHandle;
}

public enum JobObjectInfoType
{
    AssociateCompletionPortInformation = 7,
    BasicLimitInformation = 2,
    BasicUIRestrictions = 4,
    EndOfJobTimeInformation = 6,
    ExtendedLimitInformation = 9,
    SecurityLimitInformation = 5,
    GroupInformation = 11
}

[StructLayout(LayoutKind.Sequential)]
public struct JOBOBJECT_BASIC_LIMIT_INFORMATION
{
    public Int64 PerProcessUserTimeLimit;
    public Int64 PerJobUserTimeLimit;
    public JOBOBJECTLIMIT LimitFlags;
    public UIntPtr MinimumWorkingSetSize;
    public UIntPtr MaximumWorkingSetSize;
    public UInt32 ActiveProcessLimit;
    public Int64 Affinity;
    public UInt32 PriorityClass;
    public UInt32 SchedulingClass;
}

[Flags]
public enum JOBOBJECTLIMIT : uint
{
    JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE = 0x2000
}

[StructLayout(LayoutKind.Sequential)]
public struct IO_COUNTERS
{
    public UInt64 ReadOperationCount;
    public UInt64 WriteOperationCount;
    public UInt64 OtherOperationCount;
    public UInt64 ReadTransferCount;
    public UInt64 WriteTransferCount;
    public UInt64 OtherTransferCount;
}

[StructLayout(LayoutKind.Sequential)]
public struct JOBOBJECT_EXTENDED_LIMIT_INFORMATION
{
    public JOBOBJECT_BASIC_LIMIT_INFORMATION BasicLimitInformation;
    public IO_COUNTERS IoInfo;
    public UIntPtr ProcessMemoryLimit;
    public UIntPtr JobMemoryLimit;
    public UIntPtr PeakProcessMemoryUsed;
    public UIntPtr PeakJobMemoryUsed;
}


This answer started with @Matt Howells' excellent answer plus others (see links in the code below). Improvements:
  • Supports 32-bit and 64-bit.
  • Fixes some problems in @Matt Howells' answer:
    1. The small memory leak of extendedInfoPtr
    2. The 'Win32' compile error, and
    3. A stack-unbalanced exception I got in the call to CreateJobObject (using Windows 10, Visual Studio 2015, 32-bit).
  • Names the Job, so you if you use SysInternals, for example, you can easily find it.
  • Has a somewhat simpler API and less code.
Here's how to use this code:
// Get a Process object somehow.
Process process = Process.Start(exePath, args);
// Add the Process to ChildProcessTracker.
ChildProcessTracker.AddProcess(process);
To support Windows 7 requires:
In my case, I didn't need to support Windows 7, so I have a simple check at the top of the static constructor below.

Saturday, April 30, 2016

Retry Class C#

 


 

Using this class, taken from http://kb.zillionics.com/c-retry-pattern/ as my note

    class Retry
    {
        /// <summary>
        /// Retry calling of a method if it fails
        /// </summary>
        /// <typeparam name="T">Return data type</typeparam>
        /// <param name="method">Method</param>
        /// <param name="numRetries">Number of Retries</param>
        /// <param name="secondsToWaitBeforeRetry"></param>
        /// <returns>T</returns>
        public static T RetryMethod<T>(Func<T> method, int numRetries, int secondsToWaitBeforeRetry)
        {
            if (method == null)
                throw new ArgumentNullException("method");
            T retval = default(T);
            do
            {
                try
                {
                    retval = method();
                    return retval;
                }
                catch (Exception ex)
                {
                    //Logger.Log(ex.ToString());
                    //Logger.Log("Retrying... Count down: " + numRetries);
                    if (numRetries <= 0) throw;
                    Thread.Sleep(secondsToWaitBeforeRetry * 1000);
                }
            } while (numRetries-- > 0);
            return retval;
        }

        /// <summary>
        /// Retry calling of an Action if it fails
        /// </summary>
        /// <typeparam name="T">Return data type</typeparam>
        /// <param name="method">Method</param>
        /// <param name="numRetries">Number of Retries</param>
        /// <param name="secondsToWaitBeforeRetry"></param>
        public static void RetryAction(Action action, int numRetries, int secondsToWaitBeforeRetry)
        {
            if (action == null)
                throw new ArgumentNullException("action");
            do
            {
                try { action(); return; }
                catch (Exception ex)
                {
                    //Logger.Log(ex.ToString());
                    //Logger.Log("Retrying... Count down: " + numRetries);
                    if (numRetries <= 0) throw;
                    else Thread.Sleep(secondsToWaitBeforeRetry * 1000);
                }
            } while (numRetries-- > 0);
        }
    }
How to using it 

  string ret = Retry.RetryMethod(() => {
                                     string abac = ambildataimdb(line,  c, lines);
                                     return abac;
                                    }, 3, 5);
Or VOID


  Retry.RetryAction(() =>
                         {
                           ambildataimdb(line,  c, lines);
                                    }, 3, 5);

Tuesday, April 26, 2016

Richtextbox copy paste as plaintext

 


 

private void richTextBox1_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.Control && e.KeyCode == Keys.V)
            {
                richTextBox1.Text += (string)Clipboard.GetData("Text");
                e.Handled = true;
            }
        }


 On event KeyDown

NUGET, reinstall, install, uninstall

 

 

REINSTALL

Update-Package –reinstall <packageName>

REINSTALL ALL
Update-Package -Reinstall

INSTALL

Install-Package Geckofx45 

UNINSTALL  

Uninstall-Package OpenIdPortableAre


UNINSTALL with dependencies 


Uninstall-Package OpenIdPortableArea –RemoveDependencies

Sunday, April 3, 2016

MULTI THREADING ( Only What I know and worked out )

 


 

this the only one that I know and it worked out for me...

string[] ric = new string[] 
            {
                "https://www.youtube.com/watch?v=vzuQeFOiyYE",
"https://www.youtube.com/watch?v=xXdHgCao0fU",
"https://www.youtube.com/watch?v=3Fi-KxsTF9E"};


                Parallel.ForEach(
                    ric, tuple =>
                    {
                        Console.WriteLine(tuple); Thread.Sleep(1000);
                        Console.WriteLine("{0}: Extracted {1} urls", DateTime.Now, count);
                        Interlocked.Increment(ref count);
                    });
            

 

Monday, March 28, 2016

Custom Thumbnails youtube v3 ( 2 method )

 


 

I am facing a huge problem using the youtube-api. I try to set a custom thumbnail for one of my videos. Of course I have the permission to set custom thumbnails for my videos and an authenticated youtube service. I tried to do it in two ways (C#):

Method 1 using the .Net API:

    [...]
    Debug.WriteLine("Try to set thumbnail...");
    thumbnailStream = File.OpenRead(@"D:\myThumbnail.jpg");
    YouTubeService service = GetYouTubeService(); // Gets the authenticated youtube service
    ThumbnailsResource tr = new ThumbnailsResource(service);
    ThumbnailsResource.SetMediaUpload mediaUploadThumbnail = tr.Set(MY_VIDEO_ID, thumbnailStream, "image/jpeg");
    mediaUploadThumbnail.ChunkSize = 256 * 1024;
    mediaUploadThumbnail.ProgressChanged += mediaUploadThumbnail_ProgressChanged;
    mediaUploadThumbnail.ResponseReceived += mediaUploadThumbnail_ResponseReceived;
    Debug.WriteLine("... Starting async upload");
    mediaUploadThumbnail.UploadAsync();
    [...]

    void mediaUploadThumbnail_ProgressChanged(IUploadProgress obj)
    {
        Debug.WriteLine("... Progress changed");
        Debug.Write(" ... " + obj.Status.ToString() + ": " + obj.BytesSent + " bytes sent");
        if (obj.Exception != null)
        {
            Debug.Write("... Exception:" + obj.Exception.ToString());
            thumbnailStream.Close();
            uploadList[aktuelleUploadPosition].Status = UploadVideoStatus.ThumbnailFehler;
            objectListViewUploads.RefreshObjects(uploadList);
            Starte_Uploads();
        }
    }

    void mediaUploadThumbnail_ResponseReceived(ThumbnailSetResponse obj)
    {
        Debug.WriteLine("... Done: " + obj.Items[0].High.Url);
        thumbnailStream.Close();
        uploadList[aktuelleUploadPosition].Status = UploadVideoStatus.Fertig;
        objectListViewUploads.RefreshObjects(uploadList);
        Starte_Uploads();
    }

The Output of Method 1 is:

Try to set thumbnail...
... Starting async upload
... Progress changed ... Starting: 0 bytes sent
... Progress changed ... Uploading: 262144 bytes sent
... Progress changed ... Uploading: 524288 bytes sent
... Done: https://i.ytimg.com/s_vi/CjiPNurZs2M/hqdefault.jpg?sqp=CJCH958F&rs=AOn4CLA5OGm9ZfythL5cri4cjV3CyP4Pmg
... Progress changed ... Completed: 750441 bytes sent

Method 2 using direct Webrequest:

    Debug.WriteLine("Try to set thumbnail...");
    RefreshToken(); // sets a new access token or refreshes the existing on
    thumbnailStream = File.OpenRead(@"D:\myThumbnail.jpg");
    HttpWebRequest webReq = (HttpWebRequest)WebRequest.Create("https://www.googleapis.com/upload/youtube/v3/thumbnails/set?videoId=" + MY_VIDEO_ID);
    webReq.Method = "POST";
    webReq.ContentLength = thumbnailStream.Length;
    webReq.ContentType = "image/jpeg";
    webReq.Headers.Set(HttpRequestHeader.Authorization, "Bearer " + access_token);
    byte[] thumbBuffer = ReadToEnd(thumbnailStream);
    var reqStream = webReq.GetRequestStream();
    reqStream.Write(thumbBuffer, 0, thumbBuffer.Length);
    reqStream.Close();
    try
    {
        HttpWebResponse resp = (HttpWebResponse)webReq.GetResponse();
        byte[] bytes = new byte[(int)resp.ContentLength];
        resp.GetResponseStream().Read(bytes, 0, (int)resp.ContentLength);
        Debug.WriteLine("Content: " + System.Text.Encoding.UTF8.GetString(bytes));
    }
    catch (WebException ex)
    {
        byte[] bytes = new byte[(int)ex.Response.ContentLength];
        ex.Response.GetResponseStream().Read(bytes, 0, (int)ex.Response.ContentLength);
        Debug.WriteLine("Content: " + System.Text.Encoding.UTF8.GetString(bytes));
    }
    thumbnailStream.Close();

The Output of Method 2 is:

Try to set thumbnail...
Content: {
 "kind": "youtube#thumbnailSetResponse",
 "etag": "\"gMjDJfS6nsym0T-NKCXALC_u_rM/FktWbvFp7RSXY9xeTkZbzfsVtH0\"",
 "items": [
  {
   "default": {
    "url": "https://i.ytimg.com/s_vi/CjiPNurZs2M/default.jpg?sqp=CMCQ958F&rs=AOn4CLAr7zN45H1HExk4K_-y8ujYXWMBFw",
    "width": 120,
    "height": 90
   },
   "medium": {
    "url": "https://i.ytimg.com/s_vi/CjiPNurZs2M/mqdefault.jpg?sqp=CMCQ958F&rs=AOn4CLAJcATINZ2yuyNE1Ij6engYjZA5qw",
    "width": 320,
    "height": 180
   },
   "high": {
    "url": "https://i.ytimg.com/s_vi/CjiPNurZs2M/hqdefault.jpg?sqp=CMCQ958F&rs=AOn4CLBOJfds9D6hyIFDyeYzr9oug52-Lg",
    "width": 480,
    "height": 360
   }
  }
 ]
}

Result:

Both methods seem to be doing, what they are supposed to do. But if I check the images represented by the urls in the outputs, I see that they are the default “in progress image” (the one with the three dots) if no thumbnail for this video had been set before or the old thumbnail if it had been set before. The thumbnail shown for the video in my video manager is always the default “in progress image”. So no image is being set. I know that the image (D:\myThumbnail.jpg) is ok and can be set, because I can set it as a thumbnail in my video manager.

Multi threading with Windows Forms

The article taken from  http://www.codeproject.com/Articles/631514/Multi-threading-with-Windows-Forms as my note, all credits goes to author and codeproject

another example is http://stoyanov.in/2010/12/29/multithreading-with-windows-forms-in-c/


Introduction

I've come across a requirement on a number of occasions to produce a Windows application that interacts with a remote web server. The Windows application may be dealing with a web-service, or simply automating form input or screen scraping - what is common is that there is one side of the equation that is web based and therefore can potentially handle multiple requests, thus allowing us to complete the process faster. This article is a project that consists of two parts: a threaded Windows client, and a simple MVC application that it interacts with. As not all remote services allow multiple connections, the project gives the option for running the process in sequential or parallel (threaded) mode. The source code of both projects is attached.

Background

The main concept being introduced in this article is Windows multi-threading. The approach I have taken is one of many open to developers.
The technologies being demonstrated here are:
  • using an HTTPClient in async mode in a thread
  • XML messages
  • interacting with a Windows application main operating thread to update objects on the user interface in a thread safe manner
The threading concept is as follows:
  • create a thread and set its various attributes
  • when the thread completes its work, have it call back into a work-completed method in the main form thread and update the user as required.

Setting things up

The simple server - An MVC app

In order to test our work, and not trigger a denial of service warning (large numbers of multiple threads can do that!), we will create a test harness. In this case, a simple MVC application will suffice. We will create a controller method GetXML that takes in an ID sent by the Windows application, and returns an XML response.
The GetXML method is called like this: http://localhost:4174/home/GetXML?ItemID=23.
And returns output XML like this:
<response type="response-out" timestamp="20130804132059"> 
    <itemid>23</itemid>
    <result>0</result>
</response>
NB: for the purposes of this test, a "result" of 0 = failure, 1 = success.
(1) Create a new MVC app, and add a new controller GetXML. We are also going to put in a small "sleep" command to slow things down a bit and emulate delay over the very busy Interwebs.
public ContentResult GetXML()
{
    // assign post parameters to variables
    string ReceivedID = Request.Params["ItemID"];
    // generate a random sleep time in milli-seconds
    Random rnd = new Random();
    // multiplier ensures we have good breaks between sleeps
    // note that with Random, the upper bound is exclusive so this really means 1..5
    int SleepTime = rnd.Next(1, 2) * 1000;
    // generate XML string to send back
    System.Threading.Thread.Sleep(SleepTime);
    return Content(TestModel.GetXMLResponse(ReceivedID), "text/xml");
} 

(2) Create a model method that takes care of the logic of constructing the XML response to send back. This will take as parameter an ID (int) that represents the identifier of a list of objects/queries that the user is working with. These could be credit cards, websites to scrape, account numbers, etc. In reality you can send in any data you need to work with, and return then to the main calling application.
public static string GetXMLResponse(string ItemID)
{
    // generate a random result code, 0= fail, 1 = success
    // note that with Random, the upper bound is exclusive so this really means 1..2
    Random rnd = new Random();
    string ResultCode = rnd.Next(0, 2).ToString();
    string TimeStamp = GetTimeStamp();

    // create an XML document to send as response
    XmlDocument doc = new XmlDocument();

    // add root node and some attributes
    XmlNode rootNode = doc.CreateElement("response");
    XmlAttribute attr = doc.CreateAttribute("type");
    attr.Value = "response-out";
    rootNode.Attributes.Append(attr);
    attr = doc.CreateAttribute("timestamp");
    attr.Value = TimeStamp;
    rootNode.Attributes.Append(attr);
    doc.AppendChild(rootNode);

    // add child to root node sending back the item ID
    XmlNode dataNode = doc.CreateElement("itemid");
    dataNode.InnerText = ItemID;
    rootNode.AppendChild(dataNode);

    // add our random result
    dataNode = doc.CreateElement("result");
    dataNode.InnerText = ResultCode;
    rootNode.AppendChild(dataNode);
 
    // send back xml
    return doc.OuterXml;
}

The threaded client - A Windows form app

The client is visually quite simple. It contains two edit boxes for input variables, a listview to show the user what is happening, and a checkbox to tell the program if it should run in sequential or threaded mode.

We will go through the overall logic first by examining the sequential process, and then look at the threading part.
At the top of the form class we keep track of some variables:
private int RunningThreadCount;
private int RunTimes;
private int TimeStart;
Everything is kicked off by the RunProcess button click event:
TimeStart = System.Environment.TickCount;
InitProcess();
if (chkRunThreaded.Checked)
    RunProcessThreaded(); 
else RunProcess();
 
We keep track of the start time, and update this when all processes are complete to test how long the process took. We also at this stage call an Init method that sets things up for us, assigning some variables and filling the ListView with values.
// set up some default values
public void InitProcess()
{
    btnExit.Enabled = false;
    btnRunProcess.Enabled = false;
    chkRunThreaded.Enabled = false;
    RunTimes = int.Parse(edtTimesToRun.Text);
    FillListView();

    RunningThreadCount = 0;
}

// fill the ListView with the count items
public void FillListView()
{
    lvMain.Items.Clear();
    for (int i = 0; i < RunTimes; i++)
    {
        ListViewItem itm = new ListViewItem();
        itm.Text = (i+1).ToString();
        itm.SubItems.Add("Pending");
        itm.SubItems.Add("-");
        itm.SubItems.Add("-");
        lvMain.Items.Add(itm);
    } 
}
Let's now look at the sequential RunProcess method. This controls the main body of work for each web request. The number of times to run the process is set by the value of edtTimesToRun.Text which is assigned to the variable RunTimes.
The RunProcess method has a keyword of async - this is important as we are using the await keyword within the RunProcess method. The important part of this code is SendWebRequest - this takes the input, queries the web server, and returns a value that we use to update the UI for the user.
public async void RunProcess()
{
    for (int i = 0; i < RunTimes; i++)  {
        updateStatusLabel("Processing: " + (i + 1).ToString() + 
                 "/" + RunTimes.ToString());
        lvMain.Items[i].Selected = true;
        lvMain.Items[i].EnsureVisible();
        lvMain.Items[i].SubItems[1].Text = "Processing...";
        SimpleObj result = await Shared.SendWebRequest(
                                 new SimpleObj() 
                                     { ItemID = i.ToString(), 
                                       WebURL = edtTestServer.Text}
                                      );
        lvMain.Items[i].SubItems[1].Text = result.ResultCode;
        if (result.ResultCode == "ERR")
            lvMain.Items[i].SubItems[2].Text = result.Message;
    }
    CleanUp();
}
SendWebRequest is located in a separate shared.cs file as it is used from two different places. The shared.cs file also contains a simple object called SimpleObj. This is used to carry data between methods.
public class SimpleObj
{
    public string WebURL; // web address to send post to
    public string ResultCode; // 0 = failure, 1 = success
    // Used to store the html received back from our HTTPClient request
    public string XMLData;
    public string Message; // What we will show back to the user as response
    public string ItemID;
}
// Used to store the ListView item ID/index so
// we can update it when the thread completes    
The SendWebRequest method is again, flagged as async. This will be explained later.
In the SendWebRequest method, we set up an HTTPClient, calling its PostAsync method. Here we are telling the HTTPClient to perform a "POST" action against the server. If you have done web programming before, you will recall setting up a form:
<form action="somedomain.com/someaction?somevalue=134" method="post"> 
<input type="text" id="ItemID">
<input type="submit" value="send">
</form>
 
That is in effect we are doing here. We create the client object, send in as parameters the URL of the website we want to send the data to, together with the "content", which is the data packet to send. In this case the content simply consists of the parameter ItemID and its value.
HttpResponseMessage response = await httpClient.PostAsync(rec.WebURL, content);
The await keyword tells the code to sit there until with the HTTPClient comes back with a response, or an exception is raised. We examine the response to ensure it is valid (response.IsSuccessStatusCode), and assuming it is, we proceed to take the response content stream and process its XML result. Note the outer Try/Except wrapper - this will catch any HTTP connection errors and report these separately and allow the application to continue working smoothly.
public static async Task<SimpleObj> SendWebRequest(SimpleObj rec)
{
    SimpleObj rslt = new SimpleObj();
    rslt = rec;
    var httpClient = new HttpClient();

    // we send the server the ItemID
    StringContent content = new StringContent(rec.ItemID); 
    try
    {
        HttpResponseMessage response = 
            await httpClient.PostAsync(rec.WebURL, content);
        if (response.IsSuccessStatusCode)
        {
            HttpContent stream = response.Content;
            Task<string> data = stream.ReadAsStringAsync();
            rslt.XMLData = data.Result.ToString();
            XmlDocument doc = new XmlDocument();
            doc.LoadXml(rslt.XMLData);
            XmlNode resultNode = doc.SelectSingleNode("response");
            string resultStatus = resultNode.InnerText;
            if (resultStatus == "1")
                rslt.ResultCode = "OK";
            else if (resultStatus == "0")
                rslt.ResultCode = "ERR";
            rslt.Message = doc.InnerXml;
        }
    }
    catch (Exception ex)
    { 
        rslt.ResultCode = "ERR";
        rslt.Message = "Connection error: " + ex.Message;
    } 
    return rslt;
}
So, that is the basic sequential work-flow. Take a list of work items, iterate through them in sequence, call the web server, and parse back the xml response.
As the processes are run sequentially, the overall time taken to complete can be high.








Now let's run through the RunProcessThread code and see the difference.
Here is our outer wrapper method in the main form:
public void RunProcessThreaded()
{
    updateStatusLabel("Status: threaded mode - watch thread count and list status");
    lblThreadCount.Visible = true;

    for (int i = 0; i < RunTimes; i++)
    {
        updateStatusLabel("Processing: " + (i + 1).ToString() + "/" + RunTimes.ToString());
        lvMain.Items[i].Selected = true;
        lvMain.Items[i].SubItems[1].Text = "Processing...";
        SimpleObj rec = new SimpleObj() { ItemID = i.ToString(), WebURL = edtTestServer.Text };
        CreateWorkThread(rec);
        RunningThreadCount++;
        UpdateThreadCount();
    } 
} 
The critical change is that instead of carrying out the WebRequest task on each loop sequentially, we are passing that task off to the method CreateWorkThread, passing in the required parameters.
public void CreateWorkThread(SimpleObj rec){
    ThreadWorker item = new ThreadWorker(rec);
    //subscribe to be notified when result is ready
    item.Completed += WorkThread_Completed;
    item.DoWork();
} 
This small method creates a new object ThreadWorker, and tells it to call WorkThread_Completed when it is finished. The WorkThread_Completed method in the form simply updates the form UI *in the context of the form thread* and performs some cleanup.
//handler method to run when work has completed
private void WorkThread_Completed(object sender, WorkItemCompletedEventArgs e)
{
    lvMain.Items[int.Parse(e.Result.ItemID)].SubItems[1].Text = e.Result.ResultCode;
    if (e.Result.ResultCode == "ERR")
        lvMain.Items[int.Parse(e.Result.ItemID)].SubItems[2].Text = e.Result.Message;

    RunningThreadCount--;
    UpdateThreadCount();

    if (RunningThreadCount == 0)
    {
        CleanUp();
    }
}
I have created a separate class/file ThreadWorker to manage the thread work - this keeps things separate and clean.
The class has some private members and a public event:
class ThreadWorker
{
    private AsyncOperation op; // async operation representing the work item
    private SimpleObj ARec; // variable to store the request and response details
    public event EventHandler<WorkItemCompletedEventArgs> Completed;
    //event handler to be run when work has completed with a result


    // constructor for the thread. Takes param ID index of the Listview to keep track of.
    public ThreadWorker(SimpleObj Rec)
    {
        ARec = Rec;                 
    } 
}
You will recall that in our main form, when we are creating each thread worker, we set up the thread object, then tell it to DoWork so this is the main kick-off method for the thread object.
public void DoWork()
{
    //get new async op object calling forms sync context
    this.op = AsyncOperationManager.CreateOperation(null);
    //queue work so a thread from the thread pool can pick it up and execute it
    ThreadPool.QueueUserWorkItem((o) => this.PerformWork(ARec)); 
} 
 
 
The reason I am using a ThreadPool object is that creating threads is a very expensive operation therefore using the pool means that on completion, threads can be put into a pool to be reused. After being added to the pool, we tell the thread to kick off the method PreformWork. This method calls our shared method SendWebRequest, and when that is finished, calls PostCompleted which gets picked up by the WorkThread_Completed method in the main form class.
private void PostCompleted() //SimpleObj result
{
    // call OnCompleted, passing in the SimpleObj result to it,
    // the lambda passed into this method is invoked in the context of the form UI
    op.PostOperationCompleted((o) => 
      this.OnCompleted(new WorkItemCompletedEventArgs(ARec)), ARec);
}

protected virtual void OnCompleted(WorkItemCompletedEventArgs Args)
{
    //raise the Completed event in the context of the form 
    EventHandler<WorkItemCompletedEventArgs> temp = Completed;
    if (temp != null)
    {
        temp.Invoke(this, Args);
    }
}
Our main form "WorkThread_Completed" method watches each incoming terminated thread, and when they have all completed, runs some cleanup code.
//handler method to run when work has completed
private void WorkThread_Completed(object sender, WorkItemCompletedEventArgs e)
{
    lvMain.Items[int.Parse(e.Result.ItemID)].SubItems[1].Text = e.Result.ResultCode;
    if (e.Result.ResultCode == "ERR")
        lvMain.Items[int.Parse(e.Result.ItemID)].SubItems[2].Text = e.Result.Message;
    RunningThreadCount--;
    UpdateThreadCount();
    if (RunningThreadCount == 0)
    {
        CleanUp();
    }
} 
And that is it, as you can see running threaded adds a bit more code, but dramatically improves performance.






As I stated at the start of this article, this is but one way of handling a threaded application. Thread pools have their advantages and disadvantages, you need to weigh up your goals and granular needs against the ease of use. If you are interested in this area you should also look at Background worker and if you want to harness the power that is in multi-core CPUs while threading the Task Parallel Library is a great way to go.
(PS: If you found this article useful or downloaded the code please let me know by giving a rating below!)

License

This article, along with any associated source code and files, is licensed under The Code Project Open License