3

progressRing.IsActive = true;(UIスレッドを使用して)3つのListオブジェクトを生成してディスパッチしBackgroundWorker、そのリストをに転送しようとしUI Threadていますが、...で問題が発生しています。

DependencyObjectと同じスレッドにDependencySourceを作成する必要があります。

リソース、私は読んだ

BackgroundLogin()部分クラスの方法MainWindow

    private void BackgroundLogin()
    {
        //process the form on UI Thread
        this.LoginForm(FadeOut);
        this.LoadingRing(FadeIn);

        //Start a new Thread
        BackgroundWorker worker = new BackgroundWorker();
        worker.DoWork += worker_DoWork;
        worker.RunWorkerCompleted += worker_RunWorkerCompleted;
        //initialize custom class WorkerThread object to store/process a result
        WorkerThread wt = new WorkerThread(this, txtEmailAddress.Text, txtPassword.Password);
        //start the worker and send the object across.
        worker.RunWorkerAsync(wt);
    }

worker_DoWork部分クラスの方法MainWindow

    private void worker_DoWork(object sender, DoWorkEventArgs e)
    {
        //grab the object
        WorkerThread wt = (WorkerThread)e.Argument;
        //check if we can login
        if (!wt.Login())
        {
            //cancel the thread
            e.Cancel = true;
        }
        else
        {
            //load additional data
            wt.UpdateAuthLbl(".. Loading New Data ..");
            wt.LoadLists();
            wt.UpdateAuthLbl(".. Data Loaded ..");
        }
        //pass the object back
        e.Result = wt;
    }

loadLists()クラスのメソッドWorkerThread

    /// <summary>
    /// Load data into the list
    /// </summary>
    public void LoadLists()
    {
        this.gene_fact_list = db.loadGeneFactTable();
        this.gene_trait_fact_list = db.loadGeneTraitFactTable(this.gene_fact_list);
        this.category_trait_list = db.loadCategoryTraits();
    }

worker_RunWorkerCompleted部分クラスのメソッド、クラスMainWindowのオブジェクトglGeneList

    private void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        //grab the finished object
        WorkerThread wt = (WorkerThread) e.Result;
        //work out if we are logged in
        Boolean LoginFlag = !e.Cancelled && e.Error == null;
        if (LoginFlag)
        {
            lblAuthentication.Content = ".. Loading Interface ..";
            //pass the finished object into memory
            this.gl = wt;
            //reset the listbox
            this.resetListBox();
        }
        this.LoginForm(LoginFlag);
    }

方法resetListBox()ListBoxItems

    /// <summary>
    /// Load the data for the form
    /// </summary>
    public void resetListBox()
    {
        if (this.gl.notNullOrEmpty())
        {
            this.ListBoxItems.Clear();
            //begin compiling the mainTab
            foreach (KeyValuePair<long, GeneNotesDataModel> kvp in this.gl.gene_fact_list)
            {
                this.ListBoxItems.Add(kvp.Value);
            }
        }
    } //close function

    //declare WPF list binding
    private ObservableCollection<GeneNotesDataModel> _listBoxItems = new ObservableCollection<GeneNotesDataModel>();

    /// <summary>
    /// Control the listbox of rsid codes
    /// </summary>
    public ObservableCollection<GeneNotesDataModel> ListBoxItems
    {
        get { return _listBoxItems; }
        set { _listBoxItems = value; }
    }

XAML ListBoxlstSnpCodes

<ListBox ItemsSource="{Binding ElementName=UI, Path=ListBoxItems}" Margin="6,38,0,60" BorderThickness="2" HorizontalAlignment="Left" Width="180" Name="lstSnpCodes" SelectionChanged="lstSnpCodes_SelectionChanged" KeyUp="OnKeyUpHandler" />

この行this.ListBoxItems.Add(kvp.Value);により、Exceptionが発生します(これに置き換えると、Debug.WriteLine(kvp.Value.getValueAsString());問題なく実行されます)。DependencySource例外が発生する理由について何かアイデアはありますか?ListAからSlave Threadに転送できないのはなぜMain Threadですか?

PasteBinリンクは2013年4月に期限切れになります

4

1 に答える 1

1

スレッド間でプロパティに直接アクセスしようとする代わりに、その背後にある変数にアクセスしてみてください。

サンプルアプリでは:

private static List<object> _lst;


    static void Main(string[] args)
    {
        Task tsk =  new Task(() => _lst = new List<object>()); //task will create new thread if available and execute the Action.
        tsk.Start(); //initiates task, which initiates new List<object> on new thread.
        tsk.Wait(); //waits for task to complete.  Note that this locks main thread.
        _lst.Add(1); //Attempt to access _lst from main thread.
    }

あなたの例に固有です。

private ReadOnly object _lockMyList = new object();
private List _MyList;

public void SetMyList(List lst) //Use this to set list from other thread.
{
    Lock(_lockMyList)
    {
        _MyList = lst;
    }
    //Invoke Property Changed event if needed for binding.
}

public List MyList
{
    get
    {
        List lst = null;
        Lock(_lockMyList)
        {
            lst = _MyList; //You might need to do _MyList.ToList() for true thread safety
        }
        return lst;
    }
    //Property setter if needed, but use accessor method instead for setting property from other thread
}

また、SynchronizedCollection を調べて、ニーズにより適しているかどうかを確認することもできます。

これが役立つことを願っています。

于 2013-03-04T06:25:15.697 に答える