简体   繁体   中英

C# in WPF: DispatcherTimer - System.UnauthorizedAccessException: Invalid cross-thread access

I am trying to implement a timeout for my webclient. All that the client is doing is checking if there is a connection to a server. That part works fine, but by default does not timeout. That's why I am trying to implement a timer which cancels the Async-call. Here is the code:

namespace WPCordovaClassLib.Cordova.Commands
{
    public class BasicAuth : BaseCommand
    {
        //Create timer to control timeout
        DispatcherTimer timeoutTimer = new DispatcherTimer();
        WebClient webClient = new WebClient();

    public void get(string options)
    {
        //Parse data that gets passed into the plugin
        string[] passedData = JSON.JsonHelper.Deserialize<string[]>(options);

        //save data to variables

        try
        {
            //Set interval for timer, add event handler and start timer
            timeoutTimer.Interval = TimeSpan.FromSeconds(5);
            timeoutTimer.Tick += new EventHandler(timeout);
            timeoutTimer.Start();
        }
        catch (Exception e)
        {
            System.Diagnostics.Debug.WriteLine(e);
        }
        try
        {
            webClient.DownloadStringCompleted += new DownloadStringCompletedEventHandler(webClient_DownloadStringCompleted);
            //Define credentials, set header etc.
            webClient.DownloadStringAsync(uri);
        }
        catch (Exception ex)
        {
            //Catch exception and react
        }
    }

    void webClient_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
    {
        try{
            //Do stuff
        } catch{
            //Do stuff
        }
        finally
        {
            timeoutTimer.Stop();
        }
    }

    private void timeout(Object sender, EventArgs e)
    {
        timeoutTimer.Stop(); //Stop timer from beeing executed again
        webClient.CancelAsync(); //Cancel Async download
        //handle timeout
    }
}

}

So the idea is to start a timer and if that timer ticks for the first time (after 5 seconds in this case) stop the timer, cancel the Async-part and handle the timeout. Unfortunately all I get is the following Exception when I create the timer:

An Exception (first chance) of type "System.IO.FileNotFoundException" occured in mscorlib.ni.dll.

An Exception (first chance) of type "System.UnauthorizedAccessException" occured in System.Windows.ni.dll.

System.UnauthorizedAccessException: Invalid cross-thread access.

at MS.Internal.XcpImports.CheckThread()

at MS.Internal.XcpImports.SetValue(IManagedPeerBase obj, DependencyProperty property, String s)

at System.Windows.Threading.DispatcherTimer.set_Interval(TimeSpan value)

at WPCordovaClassLib.Cordova.Commands.BasicAuth.get(String options)

I haven't really worked with C# before, so there might be a simpler or better solution for it.

This is my suggestion based on the exception messages. Try to avoid setting timeoutTimer's properties in the get method. If possible, create a parameterless constructor for BasicAuth and move these lines there

timeoutTimer.Interval = TimeSpan.FromSeconds(5);
timeoutTimer.Tick += new EventHandler(timeout);

A bit guessing, but hope this work.

har07-tip fixed the problem.

It indeed seemed to work better to place those two lines plus the starting of the timer in a constructor. Also the canceling the Async-part is actually handled by the event handler of my DownloadString method. I stop the timer already in the timeout-method and than again in the webClient_DownloadStringCompleted-method.

Since the timer was stopped here already, it raised an exception. I introtuced a additional boolean to see where I was comming from and acting accordingly.

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM